刷题向》关于一道比较优秀的递推型DP(openjudge9275)(EASY+)

  先甩出传送门:http://noi.openjudge.cn/ch0206/9275/

  这道题比较经典,

  最好不要看题解!!!!!

  当然,如果你执意要看我也没有办法

  首先,显然的我们可以用 f [ i ] 和 g [ i ] 来表示在第 i 行是公牛或母牛的情况

  那么易得递推式:f [ i ] = f [ i - k - 1 ] + g [ i - k - 1 ] , g [ i ] = g [ i - 1 ] + f [ i - 1 ]

  于是通过 f [ n ] + g [ n ] 得到最后答案

  但实际上,我们可以将这两种状态合并

  加上对于k的判断就可以得到:s [ i ] = s [ i - 1 ] +( i >k + 1 ) ? s [ i - k -1 ] : 1

  就是当 i < = k 的时候,我们只需要加上前一个的全部状态+1,就是这个格子是母牛的状态加上唯一的这个格子是公牛的状态。

  而当i > k 的时候,也是考虑两种情况,不过这一格是公牛的方案数不再是1,而是s [ i - k - 1 ],然后加上就可以扫一遍解决啦

  甩题目

描述

一年一度的展会要来临了,农民约翰想要把N(1 <= N <= 100,000)只奶牛和公牛安排在单独的一行中。 约翰发现最近公牛们非常好斗;假如两只公牛在这一行中靠的太近,他们就会吵架,以至于斗殴,破坏这和谐的环境。约翰非常的足智多谋,他计算出任何两只公牛之间至少要有K (0 <= K < N)只奶牛,这样才能避免斗殴。 约翰希望你帮助他计算一下有多少种安排方法,可避免任何斗殴的的发生。约翰认为每头公牛都是一样的,每头奶牛都是一样的。因而,只要在一些相同的位置上有不同种类的牛,那这就算两种不同的方法。

输入

第一行:两个用空格隔开的数:N和K

输出

第一行:一个单独的数,即约翰可以安排的方法数。考虑到这个数可能很大,你只要输出mod 5,000,011之后的结果就可以了。

样例输入
4 2
输入注释
约翰想要一排4头牛,但是任何两只公牛之间至少有两头奶牛
样例输出
6
然后直接甩代码咯
 1 #include<stdio.h>
 2 int n,k,s[110000];
 3 int main()
 4 {
 5     scanf("%d%d",&n,&k);
 6     s[1]=2;
 7     for(int i=2;i<=n;i++)
 8         s[i]=(s[i-1]+((i>k+1)?s[i-k-1]:1))%5000011;
 9     printf("%d",s[n]);
10     return 0;
11 }

 


posted @ 2016-10-23 22:47  PencilWang  阅读(261)  评论(0编辑  收藏  举报