算法与数据结构---7.3、进阶跳台阶

算法与数据结构---7.3、进阶跳台阶

一、总结

一句话总结:

A、对于这些递推规律一眼看不出的问题,我们可以枚举前几项来找规律,
B、本题(进阶跳台阶)中,我们枚举前几项之后,轻松发现数字规律f(n)=2^(n-1),递推表达式f(n)=f(n-1)+f(n-2)+...+f(1)+1
#include <iostream>
using namespace std;
int f[10000]={0};
int main(){
    int n;
    cin>>n;
    f[1]=1;
    f[2]=2;
    //这层循环用来求f[i]
    for(int i=3;i<=n;i++){
        f[i]=1;
        for(int j=1;j<=i-1;j++){
            f[i]+=f[j];
        }
    }
    cout<<f[n]<<endl;
    return 0;
}

二、进阶跳台阶

博客对应课程的视频位置:7.3、进阶跳台阶
https://www.fanrenyi.com/video/27/286

1、问题描述

有n级的台阶,你一开始在底部,
每次可以向上迈最多n级台阶,
问到达第n级台阶有多少种不同方式。


题目位置:
变态跳台阶_牛客网
https://www.nowcoder.com/practice/22243d016f6b47f2a6928b4313c85387?tpId=13&&tqId=11162&rp=1&ru=/activity/oj&qru=/ta/coding-interviews/question-ranking

2、分析及解答

 1 /*
 2 分析:
 3 
 4 f(1)=1
 5 f(2)=2
 6 f(3)=f(2)+f(1)+1=4
 7 f(4)=f(3)+f(2)+f(1)+1=8
 8 f(5)=f(4)+f(3)+f(2)+f(1)+1=16
 9 
10 如果发现数字规律,可以直接
11 f(n)=2^(n-1)
12 
13 如果没发现数字规律,可以用递推公式
14 f(n)=f(n-1)+f(n-2)+...+f(1)+1
15 
16 */
17 #include <iostream>
18 using namespace std;
19 int f[10000]={0};
20 int main(){
21     int n;
22     cin>>n;
23     f[1]=1;
24     f[2]=2;
25     //这层循环用来求f[i]
26     for(int i=3;i<=n;i++){
27         f[i]=1;
28         for(int j=1;j<=i-1;j++){
29             f[i]+=f[j];
30         }
31     }
32     cout<<f[n]<<endl;
33     return 0;
34 }

三、跳台阶

博客对应课程的视频位置:7.2、跳台阶-高精度加法
https://www.fanrenyi.com/video/27/285

1、题目描述

题目描述
有N级的台阶,你一开始在底部,
每次可以向上跳一步或者跳两步,
问到达第N级台阶总共有多少种不同方式。

输入格式
一个数字,楼梯数。

输出格式
走的方式几种。

输入输出样例
输入
4
输出
5

数据范围
60%,N<=50
100%,N<=5000


题目位置:
P1255 数楼梯 - 洛谷 | 计算机科学教育新生态
https://www.luogu.com.cn/problem/P1255

2、分析

分析:
第1级台阶有一种方式
第2级台阶有两种方式

第3级台阶可以由第1阶走两步或第2阶走一步得出。1+2=3
第4级台阶由第2阶走两步或第3阶走一步得出。2+3=5
第5级台阶由第3阶走两步或第4阶走一步得出。3+5=8
...
所以
第n级台阶由第n-2阶走两步或第n-1阶走一步得出。

所以如果用 f(n)表示跳到第n级台阶的总方式数
所以 f(n)=f(n-1)+f(n-2)

3、没高精度只能过5个点

本题的考点除了斐波那契数列,还考高精度,没写高精度只能过5个点

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int main(){
 5     int n;
 6     int a,b,c;
 7     cin>>n;
 8     //1、确定初始值
 9     a=1;
10     b=2;
11     //2、循环做递推,3-n
12     for(int i=3;i<=n;i++){
13         //F(n)=F(n-1)+F(n-2)
14         c=b+a;
15         //保留f(n)和f(n-1)做下一轮的f(n-1)和f(n-2)
16         a=b;
17         b=c;
18     }
19     if(n==0) cout<<0<<endl;
20     else if(n==1) cout<<1<<endl;
21     else if(n==2) cout<<2<<endl;
22     else cout<<c<<endl;
23     return 0;
24 }

4、加上高精度过所有点

高精度加法,因为递推关系式里面就是加法:

f(n)=f(n-1)+f(n-2)
高精度加法位置:算法疑难(c++实现)---3、高精度加法 - 范仁义 - 博客园
https://www.cnblogs.com/Renyi-Fan/p/13066540.html
 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 //高精度数对应的结构体
 7 struct BigNum{
 8     int length=0;
 9     int v[5000];
10     BigNum(){
11         memset(v,0,sizeof(v));
12     }
13 };
14 
15 //高精度加法
16 BigNum add(BigNum a,BigNum b){
17     BigNum ans;
18     ans.length=max(a.length,b.length);
19     //逐位相加
20     for(int i=0;i<=ans.length-1;i++){
21         ans.v[i]=a.v[i]+b.v[i];
22     }
23     //处理进位
24     for(int i=0;i<=ans.length-1;i++){
25         if(ans.v[i]/10){
26             ans.v[i+1]+=ans.v[i]/10;
27             ans.v[i]%=10;
28         }
29     }
30     //判断最高位的数
31     if(ans.v[ans.length]) ans.length++;
32     return ans;
33 }
34 
35 
36 int main(){
37     int n;
38     BigNum a,b,c;
39     cin>>n;
40     //1、确定初始值
41     a.length=1;b.length=1;
42     a.v[0]=1;
43     b.v[0]=2;
44     //2、循环做递推,3-n
45     for(int i=3;i<=n;i++){
46         //F(n)=F(n-1)+F(n-2)
47         c=add(b,a);
48         //保留f(n)和f(n-1)做下一轮的f(n-1)和f(n-2)
49         a=b;
50         b=c;
51     }
52     if(n==0) cout<<0<<endl;
53     else if(n==1) cout<<1<<endl;
54     else if(n==2) cout<<2<<endl;
55     else{
56         for(int i=c.length-1;i>=0;i--){
57             cout<<c.v[i];
58         }
59         cout<<endl;
60     }
61     return 0;
62 }

四、变态跳台阶

博客对应课程的视频位置:7.4、变态跳台阶
https://www.fanrenyi.com/video/27/287

1、题目描述

题目描述
有N级的台阶,你一开始在底部,
每次可以向上迈最多K级台阶(最少1级),
问到达第N级台阶有多少种不同方式。
输入格式
两个正整数N,K。

输出格式
一个正整数,为不同方式数,由于答案可能很大,
你需要输出ans mod 100003后的结果。

输入输出样例
输入
5 2
输出
8

数据范围:
对于20%的数据,有N<=10, K<=3;
对于40%的数据,有N<=1000;
对于100%的数据,有N<=100000,K<=100。


题目位置:
P1192 台阶问题 - 洛谷
https://www.luogu.com.cn/problem/P1192

2、分析及解答

分析:
f(n)=f(n-1)+f(n-2)+...+f(n-k)

n=5,k=2
f(5)=f(4)+f(3)

初始状态:
f(1)=1

前k项的值怎么确定
这个时候,问题就变成有k级台阶,
每次可以跳k步,问达到k级台阶有多少种跳法
f(1)=1
f(2)=2
f(3)=f(2)+f(1)+1=4
f(4)=f(3)+f(2)+f(1)+1=8
f(5)=f(4)+f(3)+f(2)+f(1)+1=16

算法思路:
1、确定初始值(前k项)
2、根据递推表达式来做递推

 1 #include <iostream>
 2 using namespace std;
 3 const int mod=100003;
 4 int f[100005]={0};
 5 int main(){
 6     int n,k;
 7     cin>>n;cin>>k;
 8     //1、确定初始值(前k项)
 9     f[1]=1;
10     for(int i=2;i<=k;i++){
11         f[i]=1;
12         for(int j=1;j<=i-1;j++){
13             f[i]=(f[i]+f[j])%mod;
14         }
15     }
16     //2、根据递推表达式来做递推
17     //f(n)=f(n-1)+f(n-2)+...+f(n-k)
18     for(int i=k+1;i<=n;i++){
19         for(int j=1;j<=k;j++){
20             f[i]=(f[i]+f[i-j])%mod;
21         }
22     }
23     cout<<f[n]<<endl;
24     return 0;
25 }

 
原文地址:https://www.cnblogs.com/Renyi-Fan/p/13073671.html