递归基础练习2

来源:互联网 发布:mac版酷狗音乐传歌 编辑:程序博客网 时间:2024/05/16 17:49

1、QY等人,平时写代码的时候,喜欢吃一种叫“小鱼”的零食,用来提神醒脑(其实没有任何效果,我反而感觉他们越变越笨了)。突然小鱼的厂家做促销。凭3条小鱼尾巴,可以再换一条小鱼。而且可以一直循环下去,QY开心极了,于是拿出整个月的生活费买了N条小鱼。不过因为小鱼非常辣,所以QY每天也只能吃2条,他等某天吃光了,才会在第二天拿着鱼尾巴去换小鱼,然后继续吃。请你计算一下,最后他一共能吃多少天的小鱼呢?输入数据有多组,每组一行,仅包含一个数字N,即QY一开始买入的小鱼的数量。对应每组数据,输出QY能吃多少天,每个结果输出在一行中。

【输入样式】
1
2
3
4
5
【输出样式】
1
1
3
3
5

#include <stdio.h>/*dayCount函数,计算n条鱼能吃几天,n为鱼的数量,surplus为剩余鱼尾数量*/int dayCount(int n, int surplus){    int tail = n + surplus; //鱼尾数    if(tail == 0) return 0;    if(tail < 3) return 1;    return (n+1) / 2 + dayCount(tail / 3, tail % 3);}int main(){    int n;   //n代表鱼数    while(scanf("%d", &n) != EOF){   //当输入文件结束符时退出循环    printf("%d\n", dayCount(n, 0));    }    return 0;}

2、简单的背包问题,设有一个背包,可以放入的重量为m。现在有n件物品,质量都为正整数,从n件物品中挑选若干件,使得放入背包重量之和正好为m。找到一组解即可。输入的第一行为物品的总件数和背包的载重量,第二行为各物品的质量。输出放入背包中物品的序号和重量,每行输入一件。

【输入样式】
5 10
1 2 3 4 5
【输出样式】
5 5
4 4
1 1

#include <stdio.h>#define M 100   //常量,代表最大物品数 int quality[M] = {0};   //存放各物品重量 int backpack[M] = {0};  //记录放入背包物品的序号 /*pack函数,i代表已放入背包物品的数量-1, n为当前物品的序号, m代表背包剩余可放质量*/int pack(int i, int n, int m){    int judge = 0;  //judge代表是否找到正确结果     if(n  <= 0) return 0;    if(quality[n-1] == m){  //如果当前物品正好填满背包剩余空间,则返回1         backpack[i] = n;        return 1;    }    else if(quality[n-1] < m){  //如果当前物品质量小于背包剩余空间,则将物品放入后继续判断下一个物品         backpack[i] = n;        judge = pack(i+1, n-1, m-quality[n-1]);    }    if(!judge) return pack(i, n-1, m);  //如果当前物品质量小于背包剩余空间,则直接判断下一个物品     return 1;}int main(){    int n, m, j;    //n为物品总件数,m为背包载重量,j为循环变量     scanf("%d%d", &n, &m);    for(j = 0; j < n; j++){        scanf("%d", &quality[j]);    }    if(pack(0, n, m)){        j = 0;        while(backpack[j]){        printf("%d %d\n", backpack[j], quality[backpack[j]-1]);        j++;        }    }    return 0;}

3、任何一个正整数都可以用2的幂次方表示:
如137=2^7+2^3+2^0,同时约定用括号来表示次方,即a^b可表示为a(b),所以137可表示为2(7)+2(3)+2(0),进一步可表示为:7=2^2+2+2^0,3=2+2^0,所以137可表示为2(2(2)+2+2(0))+2(2+2(0))+2(0))。

【输入样式】
1315
【输出样式】
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)

#include <stdio.h>/*函数功能:将n用2的幂次方表示*/void powerOfTwo(int n, int m){    if(n == 1){    //程序出口        switch(m){        case 0: printf("2(0)"); break;        case 1: printf("2"); break;        case 2: printf("2(2)"); break;        default:printf("2("); powerOfTwo(m, 0); printf(")");//如果幂次大于二,将幂用2的幂次方表示        }    }    else    {        powerOfTwo(n / 2, m + 1);        if(n % 2) {            switch(m){            case 0: printf("+2(0)"); break;            case 1: printf("+2"); break;            case 2: printf("+2(2)"); break;            default:printf("+2("); powerOfTwo(m, 0); printf(")");            }        }    }}int main(){    int n;    scanf("%d", &n);    powerOfTwo(n, 0);    printf("\n");    return 0;}

4、从楼上走到楼下共有h个台阶,每一步有三种走法:
(1)走一个台阶;(2)走两个台阶;(3)走三个台阶。列举出所有可能方案。

【输入样式】
4
【输出样式】
1111
112
121
13
211
22
31

/*台阶问题*/#include <stdio.h> void step(int state[], int i, int h){ //当前走到第i+1步,剩余h级台阶     int j, k;    for(j = 1; j <= 3; j++){ //当前步走j个台阶         state[i] = j;        if(h == j){ //走完一遍即输出             for(k = 0; k <= i; k++){                printf("%d", state[k]);            }            printf("\n");        }        else if(h > j) step(state, i+1, h-j); //台阶还有剩余,继续走下一步         state[i] = 0;    }} int main(){    int h; //台阶数     int state[100] = {0}; //存放第i+1步走的台阶数     scanf("%d", &h);    step(state, 0, h);    return 0;}

5、在8*8的棋盘上,放置8个皇后(棋子),是两两之间互不攻击。所谓互不攻击是说任何两个皇后都要满足:
(1)不在棋盘的同一行;
(2)不在棋盘的同一列;
(3)不在棋盘的同一对角线上。

【输出格式】
15863724
16837425
17468253
17582463
24683175
……
(注:共有92组解,这里不一一列举。)

/*八皇后问题*/#include <stdio.h> int array[9] = {0}; //存放每个皇后所在列 int state[9] = {0}; //标记该列是否安全 int down[14] = {0}; //标记该右对角线是否安全 int up[14] = {0}; //标记该左对角线是否安全 void queen(int row){ //为第row个皇后安排位置     int col, i;    for(col = 1; col <= 8; col++){ //尝试将每个col安排给当前皇后         if(up[row+col-2] != 0 || down[col-row+7] != 0 || state[col] != 0) continue; //发生冲突,尝试下一个col         array[row] = col;        state[col] = 1;        up[row+col-2] = 1;        down[col-row+7] = 1;        if(row == 8) {            for(i = 1; i <= 8; i++){                printf("%d", array[i]);            }            printf("\n");        }        else queen(row + 1);        //回溯,恢复分配前状态         state[col] = 0;        array[row] = 0;        up[row+col-2] = 0;        down[col-row+7] = 0;            }}int main(){    queen(1);    return 0;}

6、数的全排列问题,将n个数字1,2,3,…,n的所有排列按字典顺序枚举出来。

【输入格式】
3
【输出格式】
123
132
213
231
312
321

/*全排列问题*/#include <stdio.h>void arrange(int state[][10], int i, int n){ //为第i个盒子放小球     int j, k;    for(j = 1; j <= n; j++){ //将第j个小球放入第i个盒子         if(state[1][j] != 0) continue;        state[0][i] = j;        state[1][j] = 1;        if(i == n){            for(k = 1; k <= n; k++){                printf("%d", state[0][k]);            }            printf("\n");         }        else arrange(state, i+1, n);        //回溯,将第i个盒子置空,第j个小球恢复原始状态         state[0][i] = 0;          state[1][j] = 0;    }}int main(){    int n;    int state[2][10] = {0}; //第一行保存第i个盒子放的数,第二行标记第j个小球当前状态     scanf("%d", &n);    arrange(state, 1, n);    return 0;}

7、数的组合问题。从1,2,…,n中取出m个数,将所有组合按照字典顺序列出。

【输入格式】
3 2
【输出格式】
12
13
23

/*数的组合问题*/#include <stdio.h>/*将第j个小球放入第i个盒子*/void combine(int *com, int i, int j, int n, int m){    int k;    for(; j <= n; j++){        com[i] = j;        if(i+1 == m){            for(k = 0; k < m; k++){                printf("%d", com[k]);            }            printf("\n");        }        else combine(com, i+1, j+1, n, m);        com[i] = 0;    }}int main(){    int n, m;    int com[100] = {0};    scanf("%d%d", &n, &m);    combine(com, 0, 1, n, m);    return 0;}

8、G将军有一支训练有素的军队,这个军队除开G将军外,每名士兵都有一个直接上级(可能是其他士兵,也可能是G将军)。现在G将军将接受一个特别的任务,需要派遣一部分士兵(至少一个)组成一个敢死队,为了增加敢死队队员的独立性,要求如果一名士兵在敢死队中,他的直接上级不能在敢死队中。G将军有多少种派出敢死队的方法。注意,G将军也可以作为一个士兵进入敢死队。输入的第一行包含一个整数n,表示包括G将军在内的军队的人数。军队的士兵从1至n编号,G将军编号为1。接下来n-1个数,分别表示编号为2, 3, …, n的士兵的直接上级编号,编号i的士兵的直接上级的编号小于i。输出一个整数,表示派出敢死队的方案数。由于数目可能很大,你只需要输出这个数除10007的余数即可。

【输入格式】
3
1 1
【输出格式】
4
样例说明
这四种方式分别是:
1. 选1;
2. 选2;
3. 选3;
4. 选2, 3。
数据规模与约定
对于20%的数据,n ≤ 20;
对于40%的数据,n ≤ 100;
对于100%的数据,1 ≤ n ≤ 100000。

/*这里采用了链栈存储,读者可更改为顺序栈存储*///LinkStack.hstruct Node{    int data;    Node *next;};class LinkStack{    public:        LinkStack()        {top = NULL;}        ~LinkStack();        void push(int x);        int pop();        bool isExist(int m);        void printStack();    private:        Node *top;};//LinkStack.cpp#include <iostream>#include "LinkStack.h"using namespace std;/*析构函数*/LinkStack::~LinkStack(){    Node *p;    while(top){        p = top;        top = top->next;        delete p;    }}/*压栈*/void LinkStack::push(int x){    Node *p;    p = new Node;    p->data = x;    p->next = top;    top = p;}/*弹栈*/int LinkStack::pop(){    int data;    Node *p;    if(!top) cout << "下溢";    p = top;    top = p->next;    data = p->data;    delete p;    return data;}/*判断栈中是否存在元素m*/bool LinkStack::isExist(int m){    Node *p = top;    while(p){        if(p->data == m) return true;        p = p->next;    }    return false;}/*遍历栈中元素,用于编程时对程序的检验*/void LinkStack::printStack(){    Node *p;    p = top;    while(p)    {        cout << p->data;        p = p->next;    }    cout << endl;}//Squad.cpp#include <iostream>#include "LinkStack.h"using namespace std;const int M = 100001; //树的最大结点数/*count函数:返回值为空,tree指针指向树结构,stack引用链栈结构,m表示当前处理的士兵,n代表最后一个士兵       功能:计算编号在m到n可派出敢死队的方案数。*/void count(int *tree, LinkStack &stack, int m, int n){    for(; m <= n; m++){        if(stack.isExist(tree[m])) continue;        stack.push(m); //将可派出的士兵进栈        tree[0] = (tree[0]+1) % 10007; //每进栈一次,代表生成一种新的方案        count(tree, stack, m+1, n); //计算m+1到n可派出敢死队的方案数        stack.pop(); //回溯,即出栈    }}int main(){    int tree[M] = {0}; //用顺序表存储树,数据域存放其双亲结点,下标代表士兵编号    int n; //士兵的数量    LinkStack stack; //用链栈存放当前选中的士兵    cin >> n;    for(int i = 2; i <= n; i++){        cin >> tree[i];    }    count(tree, stack, 1, n); //计算编号在m到n可派出敢死队的方案数    cout << tree[0] << endl; //树的0号元素存储可生成的方案数    return 0;}
0 0
原创粉丝点击