标第一章 递推算法
解题方法:
在已知条件和所求问题之间总存在着某种相互联系的关系,关键是前后过程之间的数量关系(即递推式),然后进行顺推或逆推。
1.求斐波那契数列的前n项和
Fibonacci 数列:0,1,1,2,3,5,8,13,21,34,……
f0= 0
f1= 1
fn= fn-1 + fn-2 ( n>= 2 )
关键代码
int n, i, a0, a1 ;
cout << "n = " ;
cin >> n ;
a0 = 0 ; a1 = 1 ;
cout << a0 << " "<< a1 << " ";
for ( i = 2; i <= n/2 ; i ++ ){
a0 = a0 + a1 ;
a1 = a1 + a0 ;
cout << a0 << " "<< a1 << " ";
if ( i % 5 == 0 ) cout << endl;
}
if ( n > (i-1)*2 ) cout<< a0+a1 << endl ; 如果n是奇数就要把最后一个输出
return 0;
2.求N层汉诺塔的移动次数
递推关系分析:
f(n)=2*f(n-1)+1
边界条件:f(1)=1
int f[1000]={0,1};
int n;
cin>>n;
for(int i=2;i<=n;i++)
f[i]=2*f[i-1]+1;
cout<<f[n]<<endl;
return 0;
3.猴子吃桃问题
猴子第一天采摘了一些桃子,第二天吃了第一天的一半多一个,第三天吃了第二天的一半多一个…直到第十天就剩下一个。问:猴子第一天摘了多少桃子?
递推关系:
f(n-1)=(f(n)+1)*2
边界条件:f(10)=1
int f[11];
f[10]=1;
for(int i=9;i>=1;i--)
f[i]=2*(f[i+1]+1);
cout<<f[1]<<endl;
return 0;
4.数字三角形
顺推法
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1005;
int A[MAXN][MAXN],F[MAXN][MAXN],N;
int main() {
cin>> N;
for(int i = 1;i <= N;i ++)
for(int j = 1;j <= i;j ++)
cin >>A[i][j];
F[1][1] = A[1][1];
for(int i = 2;i <= N;i ++)
for(int j = 1;j <= i;j ++)
F[i][j]=max(F[i-1][j-1],F[i-1][j])+A[i][j];
int ans =0;
for(int i = 1;i <= N;i ++)
ans = max(ans,F[N][i]);
cout << ans << endl;
return 0;
}
逆推法
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1005;
int A[MAXN][MAXN],F[MAXN][MAXN],N;
int max(int a,int b){
if(a>b) return a;
return b;
}
int main() {
int i; cin >> N;
for(i = 1;i <= N;i ++)
for(int j = 1;j <= i;j ++)
cin>> A[i][j];
for(i = 1;i <= N;i ++)
F[N][i]= A[N][i];
for(i = N-1;i >=1;i --)
for(int j = 1;j <= i;j ++)
F[i][j]=max(F[i+1][j],F[i+1][j+1])+A[i][j];
cout<< F[1][1] << endl;
return 0;
}
5. 有 2n 的一个长方形方格,用一个12 的骨牌铺满方格。*
#include<iostream>
using namespace std;
int main(){
int n,i,j,f[101];
cout<<"input n:"; //输入骨牌数
cin>>n;
f[1]=1;f[2]=2; //边界条件
cout<<“f[1]="<<f[1]<<endl;
cout<<“f[2]="<<f[2]<<endl;
for(i=3;i<=n;i++){ //递推过程
f[i]=f[i-1]+f[i-2];
cout<<“f["<<i<<"]="<<f[i]<<endl;
}
}
6.蜜蜂路线
一只蜜蜂在下图所示的数字蜂房上爬动,已知它只能从标号小的蜂房爬到标号大的相邻蜂房,现在问你:蜜蜂从蜂房M开始爬到蜂房N,M<N,有多少种爬行路线?
#include <iostream>
#define SIZE 15001
using namespace std;
int f[SIZE] ;
int main(){
int n, m, i;
cin >> m >> n;
f[m]=1;
f[m+1]=1;
for (i = m+2; i <= n; i++)
f[i] = f[i-1] + f[i-2];
cout << f[n] << endl;
return 0;
}
7.吃糖果
名名的妈妈从外地出差回来,带了一盒好吃又精美的巧克力给名名(盒内共有 N 块巧克力,20 > N >0)。
妈妈告诉名名每天可以吃一块或者两块巧克力。假设名名每天都吃巧克力,问名名共有多少种不同的吃完巧克力的方案。
#include<iostream>
using namespace std;
int main(){
int f[20] = {0};
f[1]= 1; f[2] = 2;
for(int i = 3; i <= 20; i++){
f[i]= f[i - 1] + f[i - 2];
}
int n;
while(cin >> n){
cout<< f[n] << endl;
}
return 0;
}
8.昆虫繁殖
每对成虫过x个月产y对卵,每对卵要过两个月长成成虫。
假设每个成虫不死,第一个月只有一对成虫,且卵长成成虫后的第一个月不产卵(过X个月产卵).
问过Z个月以后,共有成虫多少对?
#include<iostream>
using namespace std;
int main(){
long long a[101]={0},b[101]={0},i,j,x,y,z;
cin>>x>>y>>z;
for(i=1;i<=x;i++){
a[i]=1;
b[i]=0;
}
for(i=x+1;i<=z+1;i++){ //因为要统计到第z个月后,所以要for到z+1
b[i]=y*a[i-x];
a[i]=a[i-1]+b[i-2];
}
cout<<a[z+1]<<endl;
return 0;
}