跳台阶问题详解---动态规划

上台阶(初级)

有一楼梯共n级,刚开始时你在第0级,若每次只能跨上一级或二级,要走上第n级,共有多少走法?(练习题NYOJ76)

解决思路(一)

这道题呢  有两种思路   如果你经验丰富  一看就看出来是动态规划了 那么就好写了

我们来分析一下动态规划  首先  n=1  只有一种 n=2 有两种  这没有疑问 

那么 我们假设n=10   现在设上到第九层的方法是F(9)  设上到第八层的方法是F(8)

F(9) 种方法和F(8)种方法  两者中一定没有重复的  因为它们的终点都不同

那么对于第九层来说  再走一步 就到达第十层   那么 我们有F(9)种方法到达第九层 

每种方法再走一步就到十了   所以我们就有F(9)种到达第十层的方法了  同理 

对于第八层来说  我们不能走一级到达9  因为这种情况已经包含在F(9)里面了(仔细想想)

所以只能走两级 到达十  那么就有F(8)种方法到达十了  而F(8) F(9)不重复  所以F(8)+F(9)种方法到达十

再往前 7 6 5...这些都需要先经过8 9 才能到  所以都已经包含在F(8) F(9)里了 

所以  最终结论就是 F(n)=F(n-1)+F(n-2)  (n>2)   F(1)=1 F(2)=2    ------也就是斐波那契数列

解决思路(二)

如果说你不知道上面的怎么分析,那么也不要紧,因为这个问题也不是特别复杂,n=3 n=4的情况我们是完全可以手算出来的,那么观察规律,很容易就发现这是斐波那契数列了,甚至算出n=3的情况就可以大胆的试斐波那契了。但是要注意下,斐波那契数列到三四十左右就爆long long了  。注意范围。

那么,既然找规律这么容易,那我们干嘛还要考虑上面说的动态规划解法呢?

其实呢,上面的动态规划思想很重要,一定要理解,因为题目是活的,我们一定要把原理理解透彻,学会举一反三

才可以更好的应对题目的变式。

上台阶(升级版)

题目

一个台阶总共有n级,如果一次可以跳1级,也可以跳2级......它也可以跳上n级。此时一只青蛙跳上一个n级的台阶总共有多少种跳法?

解决思路

这下情况变得复杂了,你就不能用上边那个找规律的方法了。

根据上边刚才的分析,我们设跳到一级有F(1)种方法,跳到二级有F(2)种方法.....F(3)...F(4).....

F(1) ..F(2).. F(3).. F(4)...F(n)  这些方法是没有重复的  因为终点都不一样

而这次 青蛙一次最多可以跳n阶  所以不论当前处在哪一阶 他都可以一步到达n层

所以  青蛙处于1....2...3...4...n-1 时和第一个问题中处于8、9往10跳的情况是一样的

所以  我们得到式子   F(n)=F(n-1)+F(n-2)+F(n-3).......F(1)

而 F(n-1)=F(n-2)+F(n-3)+F(n-4).......F(1)

两式相减  F(n) - F(n-1)=F(n-1)   --------->即F(n)=2*F(n-1)  F(1)=1

得到式子答案就出来了,实际做题时候要注意范围和题目要求。

上台阶(变式版)

青蛙抓虫

题目描述

一只青蛙,想要捕食距离它M米处的一只昆虫。
已知青蛙的蛙跳范围为[1, N]之间,单位米(每次蛙跳距离为整数,即[1,N]之间的整数)。青蛙在0的位置,求青蛙跳到M的位置吃到昆虫的方案数。

输入

测试实例包括T组测试数据。(T <= 100)
每组测试数据为两个数字M和N,分别代表青蛙距离昆虫的距离以及蛙跳的最远距离。(0 <= M <= 1000, 0 < N <= 100)

输出

对于每组测试数据,输出青蛙吃到昆虫的方案数。数据过大,结果对1e9+7取余。

样例输入

2
5 1
5 2

样例输出

1
8

上面那个升级版的解法,因为每一个位置都可以到达n 所以   F(n)=F(n-1)+F(n-2)+F(n-3).......F(1)

而这个  题意变了  每次最多跳n   但一共长却是m    其实思路还是原来的思路

对于 小于n的位置我们还是原来的求法  对于大于n的位置   等于的是能跳到他的位置的总和

如图

跳台阶问题详解---动态规划_第1张图片

代码

#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll a[10010];
int main(){
    int T,m,n;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&m,&n);
        memset(a,0,sizeof(a));
        a[1]=1;
        for(int i=2;i<=n;i++)a[i]=(2*a[i-1])%mod;
        for(int i=n+1;i<=m;i++){
            ll sum=0;
            for(int j=i-n;j

 

你可能感兴趣的:(动态规划)