下面代码是我自己写的,看别人代码比较累,所以如果楼主愿意,可以看看下面的代码,我会尽量讲解细致一点。
#include
//sub(manth,fishleft)参数意义:manth表示第几个人分鱼,fishleft表示他分鱼时获得了多少鱼
//函数的返回结果是第manth个人分鱼时剩余的条数,如manth = 5,fishleft = 1,则表示一共捕获了3906条鱼。
int sub(int manth,int fishleft){
if(manth == 1){
fishleft = (5*fishleft +1);
printf("manth = %d,fishleft = %d\n",manth,fishleft);
return fishleft;
}
fishleft = 5*sub(--manth,fishleft)+1;
printf("manth = %d,fishleft = %d\n",manth+1,fishleft);
return fishleft;
}
int main(void){
int manth = 5;
int fishleft = 1;
printf("%d\n",sub(5,1));
return 0;
}
//我得到的结果和楼主所给程序运行结果不一致!楼主可以自己计算,如果最后一个人得到的是1条鱼,则他分鱼时应该剩余6条,manth = 2时应该剩余6*5+1 = 31条,manth = 3时,应该剩余31*5+1条,最后manth= 5,也就是分鱼开始的时候,应该剩余3906条鱼。
//楼主可以用自己的程序测试,当调用sub(2)时得到的是21,而不是31,就能证明该程序应该是用问题的。
这个程序写的不够简洁明了,它用了一个static int i全局变量来传递递归之间的数据。
题目可以抽象成这样子,就是求得一个自然数n,这个数由(5k+1)构成,同时4k也是由(5i+1)构成,4i是由(5j+1)构成,以此类推,分几次鱼,这个迭代就运行几次。
所以最简单的方法是枚举,枚举自然数n,然后验证它以及它的子集4k,是否满足构成。
#include
int sub(int n,int d) /*定义函数递归求鱼的总数*/
{
if(d==0) return 1;
if(n%5==1 && 5
}
main()
{ int i;
for(i=1;!sub(i,5);i++); /*调用递归函数*/
printf("The total number of fish is %d\n",i);
return 0;
}
谭浩强不是把递归说的很明白了吗,你要将问题不断分解啊,不要一味看别人的代码,这样没用的。
设n为总鱼数
n-1/5 *4=a拿走后剩余的
变形:n=a拿走后剩余的*(5/4) + 1
a拿走后剩余的-1/5 * 4 =b拿走后剩余的;
变形:a拿走后剩余的=b拿走后剩余的*5/4 + 1
...
d拿走后剩余的=e拿走后剩余的*5/4 + 1
因此只要确定e拿走后剩余的条数,总条数既可以求得。
int sub(int n) /*定义函数递归求鱼的总数*/
{
if (n == 1)
{
static int i = 0;
do
{
i++;
}
while (i % 5 != 0);//求得第4个拿走后剩余的鱼数i,注意不是第5个拿走后的
return (i + 1);
}
else
{
int t;
do
{
t = sub(n - 1);//获得5-(n-1)个人拿走后剩余的鱼数
}
while (t % 4 != 0);//剩余的鱼数一定要被4整除
return (t / 4 * 5+1);//公式来的
}
}
自己参悟吧,最重要是弄懂递归分析方法,以不变应万变。