核电站问题

一个核电站有n个放核物质的坑,坑排列在一条直线上。如果连续m个坑中放入核物质,则会发生爆炸。于是,在某些坑中可能不放核物质。

任务:

对于给定的n和m,求不发生爆炸的放置核物质的方案总数。

输入:

输入文件只一行,两个正整数n,m( 2<=N<50,2≤M≤5)

输出:

输出文件只有一个正整数s,表示方案总数。

样例输入:

4 3

样例输出:

13

这题我们可以用动态规划来写。写动态规划,最为核心的步骤就是找方程。我们取dp[i]表示到i这个位置一共有多少种方法。那么,由于如果连续m个坑中都放入核物质,则必会引起爆炸,所以,我们需要讨论i这个数与m的大小。

我们需要先明确一点,那就是i这个位置有两种情况,那就是放入核物质和不放入核物质。

首先:当i小于m的时候,不管我前面怎么放,都不可能连续放m个。因为当前位置小于m啊,说明我就算连续放入核物质,目前为止也没有放m个。那就肯定不会爆炸。所以这个时候,我们的动态规划方程就是dp[i] = 2 * dp[i - 1].什么意思呢,就是说,i前面的i-1位置一共有dp[i - 1]种方法,而i这个位置共有2种放法(即放或不放),所以,到i位置为止,一共有2 * dp[i - 1]种放法。

其次:当i等于m的时候,诶,那这个时候就要小心了,为啥呢?因为此时若i位置放入核物质,是会爆炸的!因为算上i位置,正好是m个。当时我们计算的时候,首先仍然按当前的i位置有两种放法计算,即dp[i] = 2 * dp[i - 1],但是这显然还是不够的,原因前面已经说了,如果此时(i位置)继续放,就到m了,就会爆炸了,所以,我需要在所有这些可能的情况中,减去当前位置放核物质的这种情况。又因为此时算上i物质正好是m,所以我只需要减去每个位置都放这一种情况就好了,因为只有这一种放法会导致爆炸。于是动态规划方程就是dp[i] = 2 * dp[i - 1] - 1.

最后:当i大于m时,这是最复杂的情况。先附上老师上课画的图:

核电站问题_#define

 是不是觉得很难懂?没事,我们慢慢分析,其实很简单。今天先睡觉了,明天继续说。

我们简单分析下i这个位置。前面的2*f(i-1)其实很好理解,就是f(i)这个位置的总放法数,不过既包括了不爆炸的,也包括了会爆炸的。所以这个时候,我们就需要把所有会爆炸的方法减去。我们考察i这个位置前面的一系列位置。从i-1开始,一直到i-m+1这个位置结束,一共有m-1个坑(1到3有3个数,而不是3-1=2个数)放入了核物质。这个时候,如果在i位置放入核物质,则肯定会爆炸。因此,i-m这个位置,一定不能放入核物质!否则在你决定是否在i位置上放核物质之前就已经爆炸了。所以,从i-1这个位置开始,一直到i-m这个位置结束,这一系列的位置上,放不放入核物质都是已经确定了的,所以这里只算一种情况。再来看i-m-1这个位置,那么这个位置放不放就不确定了,因此有f(i-m-1)种放法。这么多种放法,只要乘上前面这一种放法(从i-m到i-1的这一种放法),就是f(i-m-1),所以,此时的f(i)就等于黑板上写的那个式子了。因此,我们得出动态规划方程为:dp[i] = 2 * dp[i - 1] - dp[i - m - 1]

 代码:好啦,全部讲完了,现在我们来看看代码吧:

 



1 #include <iostream>
2 #include <algorithm>
3 #define N 100
4 long long dp[N];
5 using namespace std;
6 int main()
7 {
8 int n, m;
9 cin >> n >> m;
10 //初始条件
11 dp[0] = 1;
12 for (int i = 1; i <= n; ++i) {
13 if (i < m) {
14 //i这个位置上共有两种情况:放或不放
15 //前面有dp[i - 1]种情况,因此一共有2*dp[i - 1]这么多种情况
16 //这是n小于m的情况,即不管怎么放,总不会爆炸
17 dp[i] = 2 * dp[i - 1];
18 }
19 //这种情况对应的是n正好等于m,这个时候我就需要在原来的基础上减去每个坑都放的这一种情况
20 else if (i == m) {
21 dp[i] = 2 * dp[i - 1] - 1;
22 }
23 //现在是i>m的情况,那么这种情况下,我就需要考虑减去前面所有会炸的情况了
24 else {
25 dp[i] = 2 * dp[i - 1] - dp[i - m - 1];
26 }
27 }
28 cout << dp[n];
29 return 0;
30 }


 

运行效果:

核电站问题_#define_02

 

 Perfect!