用C语言的递归解决分鱼问题

题目:A、B、C、D、E 5个人在某天夜里合伙去捕鱼,到第二天凌晨时都疲惫不堪,于是各自找地方睡觉。第二天,A第一个醒来,他将鱼分成5份,把多余的一条鱼扔掉,拿走自己的一份。B第二个醒来,也将鱼分为5份,把多余的一条扔掉,拿走自己的一份,C、D、E依次醒来,也按同样的方法拿鱼。问他们合伙至少捕了多少条鱼?代码:#include <stdio.h>int sub(int n) /*定义函数递归求鱼的总数*/{ if (n == 1) /*当n等于1时递归结束*/ { static int i = 0; do { i++; } while (i % 5 != 0); return (i + 1); /*5人平分后多出一条*/ } else { int t; do { t = sub(n - 1); } while (t % 4 != 0); return (t / 4 * 5+1); }}main() { int total; total=sub(5); /*调用递归函数*/ printf("The total number of fish is %d尀n",total); return 0;}代码略微看的懂,但实在不知道这个流程是怎么走的,哪位大神能说下代码执行的流程呢?尤其是 t=sub(n-1)的那行,完全不知道用while控制有什么用。多谢各位啦~
2026年09月27日 02:28
有3个网友回答
网友(1):

下面代码是我自己写的,看别人代码比较累,所以如果楼主愿意,可以看看下面的代码,我会尽量讲解细致一点。

#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,就能证明该程序应该是用问题的。

网友(2):

这个程序写的不够简洁明了,它用了一个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 else return 0;
}
main()
{ int i;
for(i=1;!sub(i,5);i++); /*调用递归函数*/
printf("The total number of fish is %d\n",i);
return 0;
}

网友(3):

谭浩强不是把递归说的很明白了吗,你要将问题不断分解啊,不要一味看别人的代码,这样没用的。
设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);//公式来的
}
}
自己参悟吧,最重要是弄懂递归分析方法,以不变应万变。