NKOI 1008 核电站

核电站

Time Limit:3000MS  Memory Limit:65536K
Total Submit:153 Accepted:64

Description

一个核电站有N个放核物质的坑,坑排列在一条直线上。 如果连续M个坑中放入核物质(注:并不是总共只有M个核物质),则会发生爆炸,于是,在某些坑中可能不放核物质。
任务:对于给定的N和M,求不发生爆炸的放置核物质的方案总数

Input

一行,两个正整数N,M( 1<N≤60,2≤M≤10)

Output

每组数据只输出一个正整数S,表示方案总数。

Sample Input

4 3

Sample Output

13

Source


这是一道动规题,题意十分好理解,但是想起来却有些困难

我们可以用f[i]表示有i个坑的总方案数

由于m的值不确定,所以我们应首先讨论没有m的情况,即可以随便放的情况

当i==0时,只能选择不放,f[0]=1

当i==1时,可以放也可以不放,f[1]=2

当i==2时,第2个坑可以放也可不放,结合f[1]得到f[2]=f[1]+f[1]=4

当i==3时,第3个坑可以放也可以不放,结合f[2]得到f[3]=f[2]+f[2]=8

归纳可以得到规律f[i]=2*f[i-1]

据此可以讨论存在m的情况

当i<m时,m就相当于不存在,f[i]=2*f[i-1]

当i==m,原本全部都放的方案不可行了,所以要减去这种方案,f[i]=2*f[i-1]-1

当i>m,这也是本题最大的难点,首先先把此时的方程给出来f[i]=f[i-1]+f[i-1]-f[i-m-1]

这是显而易见的。两个f[i-1]分别代表的是f[i]位上放或者不放,也就是i<m的情况。但是f[i]上能放的条件是连续的一排上最多有m-1堆。以样例为例,当i=4时,可以知道:

如果在(4)放,在(3)号坑放的前提下(2)一定是不放的。所以要用在f[i-1](3号坑放的那一个)中排除有(2)且有(3)的那种情况。

由题意可知,如果(2)(3)都有核物质,(1)中一定没有。所以能达到图中的的状态的情况数只等于f[0],即f[i-m-1]的值。这时f[i-1]-f[i-m-1]就好理解了。

此时,问题就可以解决了,但是为了保险起见,f[]数组用了long long,事实证明是正确的

#include<iostream>
using namespace std;
long long f[70];
int main(){
    int n,m,i,j;
    cin>>n>>m;
    f[0]=1;
    for(i=1;i<=n;i++){
        if(i<m)f[i]=2*f[i-1];
        if(i==m)f[i]=2*f[i-1]-1;
        if(i>m)f[i]=2*f[i-1]-f[i-m-1];
    }
    cout<<f[n];
}

你可能感兴趣的:(NKOI 1008 核电站)