有一楼梯共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的位置 等于的是能跳到他的位置的总和
如图
代码
#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