题目链接 Links
http://poj.org/problem?id=2411
题解 Solution
好久不写题了,昨晚学长突然问我这个问题做出来还花了不少时间
看到这题第一个想法是搞出一个计数公式,发现毫无头绪。再仔细想想感觉这种问题有一点印象,也许可以通过递推之类的得到结果。这时就想到了使用动态规划,我们可以逐行逐行地进行状态转移来计算总的方案数,也就是说如果我们知道了填满前 $n-1$ 行的方案数,我们可以递推出填满前 $n$ 行的答案。
那么怎么进行状态转移呢?
假设现在我们要从第 $n-1$ 行递推到第 $n$ 行,我们不妨用$1$表示在这里竖放了一枚砖块(且$1$表示是竖放砖块的上端),那么第$n-1$行砖块的状态可以用一个$01$数组表示,比如一个列数为$5$的例子:
第一个$0$说明它是一个竖放砖块的下端,第$2$和第$3$个$1$表示它们两个分别都是一个竖放砖块的上端,而后面两个$0$有两种情况,它们既可能表示一枚横放的砖块,也有可能是两个竖放砖块的下端
继续拿这个例子说话,我们既然已经知道了第$n-1$行砖块放置的情况,那么我们就知道了哪些状态是它能够状态转移到第$n$行的, 也就是说哪些第$n$行的砖块放置状态是它能够合法地转移过来的。
以下是$01100$所有能够合法转移的状态:
这里是解释,对于第 $n-1$ 行的第一个$0$,由于下一行无法从第一列开始横着放(因为第二列必须是竖着放的下端),所以第 $n$ 行的第一列一定是$1$;对于第二列和第三列,由于在第 $n-1$ 行它们是两块竖放砖块的上端,所以第 $n$ 行的第二列和第三列必须是 $0$;而对于第$n-1$行第四列和第五列的$0$, 第 $n$ 行既可以是两块竖放砖块的上端,也可以是一块横着放的砖块。
如果你看懂了这些,不难归纳出状态转移的合法标准:
- $1$ 的对应状态是 $0$
- $0$ 的对应状态是 $1$; 但是 $0 0$ 的对应状态可以是 $00$
在动态规划的状态转移中,如果我们枚举每一个状态都用 $01$ 数组表示也太麻烦了,所以干脆就用一个数的二进制形式来表示这个 $01$ 数组 ,也就是状态压缩的技巧。所以称之为状态压缩动态规划 (abbr. 状压DP)
既然是二进制表示,就需要了解基本的位运算符号和一些基本的位操作技巧,这里不赘述。但是讲一些状压DP中最最基本的技巧: 我们要枚举 $m$ 列的所有 $01$ 状态,相当于枚举 $[0, 2^m)$ 中的所有数,所以循环就是从 $0$ 循环到 $1<<m-1$。
最后说一下其实我这个判断状态转移是否合法的办法并不高明,其实可以直接预处理出哪些状态是可以从某个状态转移而来的,但我太懒了就不想写了。。。还有一件事,这题的 $n,m$ 小的可怜,就算你写的复杂度巨大打表也是可以的 -_-
代码 Codes
1 |
|