Rqnoj105 核电站问题 题解

      又回到我可爱的Blog了~昨天偷了点懒,一篇文章也没写~今天一定抽时间补上。

      下面切入正题。

 

 

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

【输入格式】
输入文件只一行,两个正整数N,M( 1<N<50,2≤M≤5)

【输出格式】
输出文件只有一个正整数S,表示方案总数。

【样例输入】
4 3

【样例输出】
13

 

 

      这是一道线性递推类的动态规划。说实话,这道题我直接看的题解,竟然没有看懂,纠结我一节课…先把代码贴上:

 

 

1 program nuclear;
2 var
3 f:array[-6..60]of int64;
4 i,m,n:integer;
5 begin
6 readln(n,m);
7 f[0]:=1;
8 f[-1]:=1;
9 for i:=1 to n do
10 f[i]:=2*f[i-1]-f[i-m-1];
11 writeln(f[n]);
12 end.
 

 

 

      这巨短的代码理解起来还真不容易。首先,f数组存储的是到第f个坑可能出现的情况数。网上很多题解都用到分情况讨论,根据Jingo大牛的无敌思想,只要把数组向前多定m位,即-m到n即可。

      另外一个比较纠结的地方就是这个神奇的动态方程。你可以自己分析一下,如果不懂请看下文。

      我们先将方程分解,即f[i]:=f[i-1]+f[i-1]-f[i-m-1],这是显而易见的。两个f[i-1]分别代表的是f[i]位上放或者不放。但是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[0]和f[-1]都初始化为1。这可以从上文很简单的找到答案。因为当i=m(i-m-1=-1)或i=m+1(i-m-1=0)时,需要减去i,i-1,…,i-m+1都有核物质的这一种不符合题意的情况。

      现在请把鼠标滚轮向上滚,重新看一遍代码。这是你就可以体会到这段伟大的O(n)的DP代码的魅力了。

 

(saltless原创,转载请注明出处)

posted on 2010-08-09 09:41  saltless  阅读(1337)  评论(0编辑  收藏  举报

导航