算法分析 第一章
计测试一班段元伟20176441
在已知条件和所求问题之间总存在着某种相互联系的关系,
如果可以找到前后过程之间的数量关系(即递推式),那么,从问题出发逐步推到已知条件,此种方法叫逆推。
无论顺推还是逆推,其关键是要找到递推式。
1 . 求菲波那契数列的前 n 项
Fibonacci 数列:0,1,1,2,3,5,8,13,21,34,……
f0 = 0
f1 = 1
fn = fn-1 + fn-2 ( n >= 2 )
#include
using namespace std ;
int main(){
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 ;
return 0;
}
2. 求 N 层汉诺塔的移动次数
递推关系分析
f(n)=2f(n-1)+1
边界条件:f(1)=1.
#include
using namespace std;
int main(){
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)=f(n-1)/2-1
f(n-1)=(f(n)+1)2
边界条件:f(10)=1
#include
using namespace std;
int main(){
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. 数字三角形
顺推法
题目要求从(1,1)出发到最底层路径最大权值和,路径中是各个点串联而成,路径起点固定,终点和中间点相对不固定。
定义F[x][y]表示从(1,1)出发到达(x,y)的路径最大权值和。
#include
#include
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
#include
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
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. 蜜蜂路线
#include
#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;
}
- 吃糖果
#include
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 . 昆虫繁殖
#include
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;
}
9 位数问题
#include
using namespace std;
int main(){
int f[1001][2],n,i,x=9;
cin>>n;
f[1][1]=1;f[1][0]=9;
for(i=2;i<=n;i++) {
if(i==n) // i是最高位
x–;
f[i][0]=(f[i-1][0]*x+f[i-1][1])%12345;
f[i][1]=(f[i-1][1]*x+f[i-1][0])%12345;
}
cout<<f[n][0];
return 0;
}
来源:https://blog.csdn.net/qq_45650149/article/details/100898564