C语言递归解决分鱼问题
来源:互联网 发布:淘宝联盟余额提现时间 编辑:程序博客网 时间:2024/04/28 15:54
A、B、C、D、E这5个人合伙夜间捕鱼,凌晨时都已经疲惫不堪,于是各自在河边的树丛中找地方睡着了。第二天日上三竿时,A第一个醒来,他将鱼平分为5份,把多余的一条扔回河中,然后拿着自己的一份回家去了;B第二个醒来,但不知道A已经拿走了一份鱼,于是他将剩下的鱼平分为5份,扔掉多余的一条,然后只拿走了自己的一份;接着C、D、E依次醒来,也都按同样的办法分鱼。问这5人至少合伙捕到多少条鱼?每个人醒来后所看到的鱼是多少条?
这里实际包含了一个隐含条件:假设Xn为第n(n=1、2、3、4、5)个人分鱼前鱼的总数,则(Xn-1)/5必须为正整数,否则不合题意。(Xn-1)/5为正整数即(X〜l)mod5=0必须成立。
又根据题意,应该有下面等式:
X4=4(X5-1)/5
X3=4(X4-1)/5
X2-4(X3-1)/5
X1=4(X2-1)/5
则一旦给定X5,就可以依次推算出X4、X3、X2和X1的值。要保证X5、X4、X3、X2和X1都满足条件(Xn-1)mod5=0,此时的X5则为5个人合伙捕到的鱼的总条数。显然,5个人合伙可能捕到的鱼的条数并不唯一,但题目中强调了 “至少”合伙捕到的鱼,此时题目的答案唯一。该问题可使用递归的方法求解。
通过这个循环,就可以对每一个的可能情况进行检查。当然,是通过调用分鱼的递归函数来进行检查的。
分鱼的递归函数如下:
fish()函数中包含了两个参数:n和x。n表示参与分鱼的人数,x表示n个人分鱼前鱼的总条数。这两个参数都是由main()函数中传递进来的。
根据前面的分析,当n=5时,(x-1)mod5==0必须成立,否则该x值不是满足题意的值,退出fish()函数,返回到main()函数,main()函数中再传递新的x值到fish中进行检验。如果(x-1)mod5==0条件成立,则要判断n=4时,(x-1)mod5=0条件是否成立,需要注意的是,此时的形参x是4个人分鱼前鱼的总条数,即f(5,x)递归调用f(4,(x-1)/5*4)。这样依次进行下去,直到n=1时,(x-1)mod5==0条件仍成立,则说明开始从main()函数中传递进来的x值是符合题意要求的一个值,可以逐层从递归函数中返回,每次返回值都为1,直至返回到main()函数。
下面是完整的代码:运行结果:
五个人合伙捕到的鱼总数为3121
递推法:利用问题本身所具有的递推关系来求解。所谓的递推关系指的是:当得到问题规模为n-1的解后,可以得出问题规模为n的解。因此,从规模为0或1的解可以依次递推出任意规模的解。
下面是完整的代码:运行结果:
fish[1]=3121
fish[2]=2496
fish[3]=1996
fish[4]=1596
fish[5]=1276
问题分析
假设5个人合伙捕了x条鱼,则“A第一个醒来,他将鱼平分为5份,把多余的一条扔回河中,然后拿着自己的一份回家去了”之后,还剩下4(x-1)/5条鱼。这里实际包含了一个隐含条件:假设Xn为第n(n=1、2、3、4、5)个人分鱼前鱼的总数,则(Xn-1)/5必须为正整数,否则不合题意。(Xn-1)/5为正整数即(X〜l)mod5=0必须成立。
又根据题意,应该有下面等式:
X4=4(X5-1)/5
X3=4(X4-1)/5
X2-4(X3-1)/5
X1=4(X2-1)/5
则一旦给定X5,就可以依次推算出X4、X3、X2和X1的值。要保证X5、X4、X3、X2和X1都满足条件(Xn-1)mod5=0,此时的X5则为5个人合伙捕到的鱼的总条数。显然,5个人合伙可能捕到的鱼的条数并不唯一,但题目中强调了 “至少”合伙捕到的鱼,此时题目的答案唯一。该问题可使用递归的方法求解。
程序设计
在main()函数中构建一个不定次数的do-while循环。定义变量x表示5个人合伙可能捕到的鱼的条数,可以取x的最小值为6,让x值逐渐增加,x每一次取值,都增加5,直到找到一个符合问题要求的答案。由于题目中问“这5人至少合伙捕到多少条鱼”,而我找到的第一个x值就是5个人至少捕到的鱼的总条数。通过这个循环,就可以对每一个的可能情况进行检查。当然,是通过调用分鱼的递归函数来进行检查的。
分鱼的递归函数如下:
fish()函数中包含了两个参数:n和x。n表示参与分鱼的人数,x表示n个人分鱼前鱼的总条数。这两个参数都是由main()函数中传递进来的。
根据前面的分析,当n=5时,(x-1)mod5==0必须成立,否则该x值不是满足题意的值,退出fish()函数,返回到main()函数,main()函数中再传递新的x值到fish中进行检验。如果(x-1)mod5==0条件成立,则要判断n=4时,(x-1)mod5=0条件是否成立,需要注意的是,此时的形参x是4个人分鱼前鱼的总条数,即f(5,x)递归调用f(4,(x-1)/5*4)。这样依次进行下去,直到n=1时,(x-1)mod5==0条件仍成立,则说明开始从main()函数中传递进来的x值是符合题意要求的一个值,可以逐层从递归函数中返回,每次返回值都为1,直至返回到main()函数。
下面是完整的代码:
- #include<stdio.h>
- /*分鱼递归函数*/
- int fish(int n, int x)
- {
- if((x-1)%5 == 0)
- {
- if(n == 1)
- return 1; /*递归出口*/
- else
- return fish(n-1, (x-1)/5*4); /*递归调用*/
- }
- return 0; /*x不是符合题意的解,返回0*/
- }
- int main()
- {
- int i=0, flag=0, x;
- do
- {
- i=i+1;
- x=i*5+1; /*x最小值为6,以后每次增加5*/
- if(fish(5, x)) /*将x传入分鱼递归函数进行检验*/
- {
- flag=1; /*找到第一个符合题意的x则置标志位为1*/
- printf("五个人合伙捕到的鱼总数为%d\n", x);
- }
- }
- while(!flag); /*未找到符合题意的x,继续循环,否则退出循环*/
- return 0;
- }
五个人合伙捕到的鱼总数为3121
知识点补充
本题还可以使用“递推法”来求解。下面先对递推法做下简介。递推法:利用问题本身所具有的递推关系来求解。所谓的递推关系指的是:当得到问题规模为n-1的解后,可以得出问题规模为n的解。因此,从规模为0或1的解可以依次递推出任意规模的解。
下面是完整的代码:
- #include<stdio.h>
- /*分鱼递归函数*/
- int fish(int n, int x)
- {
- if((x-1)%5 == 0)
- {
- if(n==1)
- return 1; /*递归出口*/
- else
- return fish(n-1, (x-1)/5*4); /*递归调用*/
- }
- return 0; /*x不是符合题意的解,返回0*/
- }
- int main()
- {
- int fish[6], i;
- fish[5]=6;
- while(1)
- {
- for(i=4; i>0; i--)
- {
- if(fish[i+1]%4!=0)
- break;
- fish[i]=fish[i+1]*5/4+1;
- if(fish[i]%5!=1)
- break;
- }
- if(i == 0)
- break;
- fish[5]+=5;
- }
- for(i=1; i<=5; i++)
- printf("fish[%d]=%d\n", i, fish[i]);
- return 0;
- }
fish[1]=3121
fish[2]=2496
fish[3]=1996
fish[4]=1596
fish[5]=1276
阅读全文
0 0
- C语言递归解决分鱼问题
- 利用Python/C语言解决分鱼问题
- c语言 递归解决约瑟夫问题
- c语言 递归算法解决汉诺塔问题
- 八皇后问题:递归解决/C语言(基础方法)
- C语言 递归(回溯) 解决数独问题
- C语言:分苹果问题
- C语言递归解决数独
- 递归算法 解决fabonaci数列 C语言
- C语言算法-猴子分桃问题
- 用C语言解决(hanoi)汉诺塔问题——函数的递归调用
- 李洋疯狂C语言之用递归解决李白喝酒问题(二)
- C语言通过递归调用函数解决求阶乘和ACKERMAN函数问题
- <C语言>用递归调用函数解决穷举n位二进制数问题
- C语言解决随机数问题
- c语言解决汉诺塔问题
- c语言 解决汉诺塔问题
- 递归求解N皇后问题(c语言)
- 《数据结构》C++代码 堆(优先队列)
- poj2385
- 第八届福建省大学生程序设计竞赛-重现赛I Magic
- 第八届福建省大学生程序设计竞赛-重现赛 L Tic-Tac-Toe
- NIM游戏-博弈论(poj2975+CodeForces
- C语言递归解决分鱼问题
- git命令
- 二、服务注册和服务发现-Eureka 的使用
- BigDecimal-精确表示货币值1
- New 一个对象
- 系统日志
- php 数组元素快速去重
- oracle 11g的安装过程
- caffe中forward过程总结(1)