一.一个人赶着鸭子去每个村庄卖,每经过一个村子卖去所赶鸭子的一半又一只。这样他经过了七个村子后还剩两只鸭子,问他出发时共赶多少只鸭子?经过每个村子卖出多少只鸭子?
1.题目分析
经过7个村庄后还剩两只鸭子,每经过一个村庄卖当前鸭子的一半加一只,所以递归体是经过前一个村子的鸭子数除以2再减去1就是到达下一个村子的时候的鸭子数,所以要想求在第一个村子的鸭子数,必须从后往前推。
2.算法构造
当村子数i=0,鸭子数number=2;当村子数0<i<7,经过第i个村子前的鸭子数number=(number+1)*2,在经过第i 个村子时卖的鸭子数m=number/2+1;
3.算法实现
见文件sellduck.c
#include<stdio.h>
/*
*author:软工1604 徐於敏 16408070731
*date:2018-11-15
*description:一个人赶着鸭子去每个村庄卖,每经过一个村子卖去所赶鸭子的一半又一只。这样他经过了七个村子后还剩两只鸭子,问他出发时共赶多少只鸭子?经过每个村子卖出多少只鸭子?
*function:sellduck()函数定义了1个全局变量i代表村子的数量,通过递归实现了计算出发时的鸭子数量
*version:0.1
*/
int number=2;//最后的鸭子数量
int m;//用来记录经过每个村子卖出的鸭子数量
int main()
{
sellduck(7);
}
int sellduck(int i)
{
if(0==i)//i为0时候结束
{
printf("他出发时一共赶了%d只鸭子",number);
}
else{
number=(number+1)*2; //计算在经过第i个村子前的鸭子数number
m=number/2+1; //计算在经过第i 个村子时卖的鸭子数m
printf( "经过第%d个村子时,他卖出%d只鸭子。\n",i,m);
i--;//村子数量-1
return sellduck(i);
}
}
4.运行结果
二.角谷定理。输入一个自然数,若为偶数,则把它除以2,若为奇数,则把它乘以3加1。经过如此有限次运算后,总可以得到自然数值1。求经过多少次可得到自然数1。
如:输入22,
输出 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
STEP=16
1.题目算法分析
先判断输入的数字是偶数还是奇数,是偶数除以2,是奇数乘以3加1,如此反复调用自身,每做完一次步数+1,并输出此时的数字,最后得到得到的数字为1,此时递归结束
2.算法实现
见solvejiaogu.c
#include<stdio.h>
/*author:软工1604 徐於敏 16408070731
*date:2018-11-15
*description:.角谷定理。输入一个自然数,若为偶数,则把它除以2,若为奇数,则把它乘以3加1。
*经过如此有限次运算后,总可以得到自然数值1。求经过多少次可得到自然数1。
*function:定义一个solve()函数,n代表一开始输入的自然数,step代表步数,通过递归实现角谷定理
*version:0.1
*/
int main()
{
int a;
printf("输入一个自然数:");
scanf("%d",&a);
solve(a,1);
}
int solve(int n,int step)
{
if(n%2==0){//判断是否为偶数,是偶数除以2
n=n/2;
printf("%d\n",n);
step++;//步数+1
}
else {//否则是奇数,将他乘以3加1
n=n*3+1;
printf("%d\n",n);
step++;//步数+1
}
if(n==1){
printf("总的步数是%d次",step);
}
if(n!=1){//若当前得到的数字为1,结束递归,否则继续
solve(n,step);
}
}
3.运行结果
三.电话号码对应的字符组合:在电话或者手机上,一个数字如2对应着字母ABC,7对应着PQRS。那么数字串27所对应的字符的可能组合就有3*4=12种(如AP,BR等)。现在输入一个3到11位长的电话号码,请打印出这个电话号码所对应的字符的所有可能组合和组合数。
1.题目分析
2对应ABC,3对应DEF,4对应GHI,5对应JKL,6对应MNO,7对应PQRS,8对应TUV,9对应WXYZ,1和0对应空。
2.算法构造
当输入一个数字时,返回这个数字所有可能性的组合。递归体是当输入一串数字,每个数字代表不同的字符串,返回最后一个数字跟前面已产生的字符串进行组合,所以首先应该建一个数组,用来存放每个数字代表的字符串组合,然后在建一个数组,用来存放每个字符串的长度,在函数中,先进行判断是否是最后一位,然后根据判断执行函数。
3.算法实现
见phone.cpp
/*
*author:软工1604 徐於敏 16408070731
*date:2018-11-15
*description:电话号码对应的字符组合:在电话或者手机上,一个数字如2对应着字母ABC,7对应着PQRS。那么数字串27所对应的字符的可能组合就有3*4=12种(如AP,BR等)。现在输入一个3到11位长的电话号码,请打印出这个电话号码所对应的字符的所有可能组合和组合数。
*function:通过递归函数tellphone实现
*version:0.1
*/
#include<iostream>
using namespace std;
char* phone[10]={"","","ABC","DEF","GHI","JKL","MNO","PQRS","TUV","WXYZ"};//数组phone用来存放数字对应的字母
int num[10]={0,0,3,3,3,3,3,4,3,4};//数组num用来存放每一个数字对应的字母的数量
char input[15];//数组input存放输入的电话号码
char output[15];//数组ouput存放输出的组合
void tellphone(int n,int len)
{
if(n == len)
{
cout<<output<<endl;
}
for(int i=0; i<num[input[n]]; i++)
{
output[n] = phone[input[n]][i];
tellphone(n+1,len);
}
}
int main()
{
int len;
printf("输入一个3到11位长的电话号码:");
scanf("%s",input);
printf("该电话号码所对应字符的所有可能的组合是:\n");
len=strlen(input);//统计输入的电话号码的长度
int count = 1;
for(int i=0; i<len; i++)//计算组合数量
{
input[i] -= '0';
count *= num[input[i]];
}
tellphone(0,len);//调用函数
cout<<"组合数:"<<count<<endl;///输出组合数量
return 0;
}
3.运行结果
四.日本著名数学游戏专家中村义作教授提出这样一个问题:父亲将2520个桔子分给六个儿子。分完 后父亲说:“老大将分给你的桔子的1/8给老二;老二拿到后连同原先的桔子分1/7给老三;老三拿到后连同原先的桔子分1/6给老四;老四拿到后连同原先的桔子分1/5给老五;老五拿到后连同原先的桔子分1/4给老六;老六拿到后连同原先的桔子分1/3给老大”。结果大家手中的桔子正好一样多。问六兄弟原来手中各有多少桔子?
1.题目分析
每个儿子拿到的橘子数目分别是原有的和现有的,除了老大,其他的儿子原有的+别人给的-给别人的=现有的=平均数,所以,可以得出原有的=现有的+给别人的-别人给的。
2.算法构造
当老几n>6,结束;当0<n<6时,算出分给下一个人的桔子数,下一个人的桔子数,下一人加上之前的桔子数的总数,接着一个个调用实现
3.算法实现
见orange.cpp
/*
*author:软工1604徐於敏16408070731
*date:2018-11-15
*description:日本著名数学游戏专家中村义作教授提出这样一个问题:父亲将2520个桔子分给六个儿子。分完 后父亲说:“老大将分给你的桔子的1/8给老二;老二拿到后连同原先的桔子分1/7给老三;老三拿到后连同原先的桔子分1/6给老四;老四拿到后连同原先的桔子分1/5给老五;老五拿到后连同原先的桔子分1/4给老六;老六拿到后连同原先的桔子分1/3给老大”。结果大家手中的桔子正好一样多。问六兄弟原来手中各有多少桔子?
version:0.1
*/
#include<iostream>
using namespace std;
int orange(int n,int before, int after,int m )//n是老几,before是之前的数量,after是之后的数量,m是从八分之一开始的分桔子的比例
{
if(n>6)//结束条件
{
return 0;
}
else
{
printf("老%d原有的桔子数:%d\n",n,before);
int givenum = after/m;//分给下一个人的桔子数
int nextBnum = 420*(m-1)/(m-2)-givenum;//下一个人的桔子数
int afterGetnum = nextBeforenum+givenum;//下一人加上之前的桔子数的总数
return orange(n+1,nextBeforenum,afterGetnum,m-1);
}
}
int main()
{
orange(1,240,240,8);
}```
4.运行结果
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181117154556919.PNG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTIyMDgzMw==,size_16,color_FFFFFF,t_70)
五.归纳总结
递归的解决首要就是,找到递归体和递归出口,将大问题分解成小问题,将小问题分解成可以直接解决的问题,在往上推,最终解决问题。