递归基础练习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;}
- 递归基础练习2
- 递归基础练习
- 基础 递归练习
- JAVASE基础-day23(递归练习)
- 基础练习 FJ的字符串(递归)
- Java基础复习(四)-递归练习
- 递归练习
- 递归练习
- 递归 练习
- 递归练习
- 递归练习
- 递归练习
- 递归练习
- 递归练习
- 递归练习
- 递归练习
- 蓝桥杯 基础练习 Sine之舞 【递归简单运用】
- SQL基础练习2
- 【LWJGL官方教程】批渲染
- JAVA-享元设计模式
- Android Studio——android中minLines和maxLines的区别
- WampServer 打造 https 站(上) 图文详解
- javascript基本学习
- 递归基础练习2
- android中的网络请求(以注册登陆为例)
- 欢迎使用CSDN-markdown编辑器
- 【学习】Javascript设计模式——Constructor构造器模式
- Java中 /** */注释和 /* */注释 的区别
- qt用mingw编译时报错 multiple definition of
- Android仿QQ长按删除弹出框
- struts2拦截器
- 正则效率,\w误区