6月15日,晴。布谷鸟叫最愁肠, 收罢山蚕麦又黄。 昨夜一场梅子雨, 催得万家割麦忙。
例2 猴子吃桃:有一堆桃子不知数目,猴子第一天吃掉一半,觉得不过瘾,又多吃了一只,第二天照此办理,吃掉剩下桃子的一半另加一个,天天如此,到第十天早上,猴子发现只剩一只桃子了,问这堆桃子原来有多少个?
俺老猪最喜欢吃桃子了,这道题目有点难?但我掰着指头可以算出每一天的剩下的桃子,然后...?
:
第10天......剩余1个桃子;
第 9天......剩余4个桃子;
第 8天......剩余10个桃子;
老猪的一贯伎俩就是枚举,碰到比较复杂的问题就很繁琐,能不能找一找规律性的东西?
老猪光吃不动脑筋,俺沙悟净来捋一捋:
第10天的桃子数:a10=1;
第9天的桃子数:a9=2 * ( a10+ 1 );
第8天的桃子数: a8=2 * ( a9+ 1 );
...
第i天的桃子数:ai=2 * ( ai+1 + 1 );
1、任务分析
2、流程图
3、代码实现
/*
ID: xianzws1
PROG: peach
LANG: C++
*/
#include <stdio.h>
#include <ctype.h>
int main() {
int sum,a[11],i;
//初始化第十天的桃子数为1
sum=a[10]=1;
for( i=9; i>0; i--) {//从第九天起,倒推每一天剩余的桃子数
a[i]=2*(a[i+1]+1);
sum = a[i];
}
printf("%d\n",sum);
return 0;
}
问题求解一般从初始的一个或若干个数据项出发,通过递推关系逐步推进,从而得到最终结果,这种求 解问题的方法叫“递推法”。其中,初始的若干数据项称为“边界”。
解决递推问题有三个重点:如何建立正确的递推关系 ? 递推关系有何性质 ? 递推关系式如何求解?
按照推导问题的方向,递推分为: 逆推法 和 顺推法。
问题分析: 已知条件第 10 天剩下 1 个桃子,隐含条件每一次前一天的桃子个数等于后一天桃子的个数加 1 的 2 倍。 采取逆向思维的方法,从后往前推,可用逆推法求解。
/*
ID: xianzws1
PROG: peach
LANG: C++
*/
#include <stdio.h>
int main() {
int a=1,i;
for (i=9; i>=1; i--)
a=(a+1)*2;
printf("%d",a);
return 0;
}
例3 A、B、C、D、E 五人合伙夜间捕鱼,凌晨时都疲惫不堪,各自在湖边的树丛中找地方睡着了。日上三竿,A第一个醒来,他将鱼平分作五份,把多余的一条扔回湖中,拿自己的一份回家去了。B第二个醒来,也将鱼平分为五份,扔掉多余的一条,只拿走自己的一份。接着 C、D、E 依次醒来,也都按同样的办法分鱼。问五人至少合伙捕到多少条鱼?每个人醒来后看到的鱼数是多少条?
俺自西海龙王三太子变身为白龙马,皈依佛门,载乘唐僧上西天取经,虽不及猴哥机灵,但也颇通算法,俺来分析一下此题。
问题分析:
假定A、B、C、D、E 五人的编号分别为1、2、3、4、5,整数数组 fish[k]表示第 k 个人所看到的鱼数。fish[1] 表示A所看到的鱼数,fish[2] 表示 B 所看到的鱼数……
fish[1] A所看到的鱼数,合伙捕到鱼的总数
fish[2]=(fish[1]-1)*4/5 B所看到的鱼数
fish[3]=(fish[2]-1)*4/5 C所看到的鱼数
fish[4]=(fish[3]-1)*4/5 D所看到的鱼数
fish[5]=(fish[4]-1)*4/5 E 所看到的鱼数 写成一般式
这个公式可用于知A 看到的鱼数去推算 B 看到的,再推算 C 看到的,…….。现在要求的是 A 看到的。能否倒过来,先知 E 看到的再反推 D 看到的,……,直到A看到的。为此将上式改写为:
fish[ i-1 ] = fish[i ] * 5 / 4 +1 i = 5, 4,…,2
分析上式
1. 当 i= 5 时,fish[5 ] 表示 E醒来所看到的鱼数,该数应满足被5整除后余1,即
fish[5 ] % 5 == 1
2. 当 i= 5 时,fish[i-1 ] 表示 D醒来所看到的鱼数,这个数既要满足
fish[4 ] = fish[ 5 ] * 5 / 4 + 1 又要满足
fish[4 ] % 5 == 1
显然,fish[ 4 ] 不能不是整数,这个结论同样可以用至 fish[ 3 ], fish[ 2 ] 和fish[ 1 ]3 . 按题意要求 5 人合伙捕到的最少鱼数,可以从小往大枚举,可以先让E 所看到的鱼数最少为 6 条,即 fish[ 5 ] 初始化为 6 来试,之后每次增加 5 再试,直至递推到 fish[ 1 ] 得整数且除以 5 之后的余数为 1。
根据上述思路,我们可以构思如下的程序框图:
该图可分为三部分
(1)是说明部分:包含定义数组fish[6],并初始化为 1 和定义循环控制变量 i,并初始化为 0。
(2)是do….while 直到型循环,其循环体又含两块:
(2).1是枚举过程中的fish[5] 的初值设置,一开始 fish[5]=1+5; 以后每次增5。
(2).2是一个for 循环,i的初值为 4,终值为 1,步长为 -1,该循环的循环体是一个分支语句,如果fish[i+1]不能被 4 整除(因为fish[ i+1 ] * 5 / 4 + 1必定是整数
),则跳出 for 循环(使用 break 语句;)否则,从 fish[i+1] 算出fish[i]。
当由break 语句让程序退出循环时,意味着某人看到的鱼数不是整数,当然不是所求,必须令fish[ 5 ] 加 5 后再试,即重新进入直到型循环 do while 的循环体。
当着正常退出for 循环时,一定是控制变量 i从初值 4,一步一步执行到终值 1,每一步的鱼数均为整数,最后 i= 0,表示计算完毕,且也达到了退出直到型循环的条件。
(3)输出计算结果
/*
ID: xianzws1
PROG: fish
LANG: C++
*/
#include <iostream> // 预编译命令
using namespace std;
int main() { //主函数
int fish[6]= {1,1,1,1,1,1}; // 整型数组,记录每人醒来后看到的鱼数
int i=0;
do {
fish[5]=fish[5]+5; // 让E看到的鱼数增5。
for (i=4; i>=1; i--) {
if ( fish[i+1]%4 !=0 )
break; // 跳出for循环
else
fish[i]=fish[i+1]*5/4+1;// 计算第i人看到的鱼数
}
} while( i>=1 ); // 当 i>=1 继续做do循环
// 输出计算结果
for (i=1; i<=5; i++)
cout << fish[i] << endl;
return 0;
}
例4:猴子分食桃子 五只猴子采得一堆桃子,猴子彼此约定隔 天早起后再分食。不过,就在半夜里,一只猴 子偷偷起来,把桃子均分成五堆后,发现还多 一个,它吃掉这桃子,并拿走了其中一堆。第 二只猴子醒来,又把桃子均分成五堆后,还是 多了一个,它也吃掉这个桃子,并拿走了其中 一堆。第三只,第四只,第五只猴子都依次如 此分食桃子。那么桃子数最少应该有几个呢?
嘿嘿,俺土地公也模仿写一个
/*
ID: xianzws1
PROG: monkey
LANG: C++
*/
#include <stdio.h>
int main() {
int x,s,k,i;
x=6; //第五只猴子面前最少的桃子数
k=0; //整除标志
while ( k!=4) {
s=x;
k=0;
for ( i=4; i>=1; i--) {
if ( s%4 ==0) k++;
else break;
s=s*5/4+1;
}
x=x+5;
}
printf("s=%d\n",s);
return 0;
}
![大笑](http://static.blog.csdn.net/xheditor/xheditor_emot/default/laugh.gif)