链接:矩形覆盖
题目详情:
我们可以用 2 ∗ 1 2*1 2∗1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个 2 ∗ 1 2*1 2∗1的小矩形无重叠地覆盖一个 2 ∗ n 2*n 2∗n的大矩形,总共有多少种方法?
分析:
- 看这样一个图,假如第列的那排用竖的填充,标为1,那么显然剩下的n-1列的排列方案数量就是它这样排的方案数;
- 如果第n列第一行用横的填充,那么下一行和前一列这四块格子中明显都要标记为0,于是这样排的方案数就是剩下的n-2列的方案数;
- 根据以上两点,我们设计状态:dp[n]表示n列2行的方格填充格子的方案数,于是可以得出转移方程:dp[n]=dp[n-1]+dp[n-2],dp[0] = 1,dp[1] = 1,恰好是斐波那契数列
这个问题我们还可以再想一个进阶点的问法:如果方格是3行n列的呢?方案数为多少?
分析:
由于砖块还是
1
∗
2
1*2
1∗2的大小,但现在已经没有满足那个一个格子定一个状态就能确定同列另一个格子的状态,比如第一行标为0,下一行可以为1也可以为0。参考英雄哪里出来大牛的做法,由于一维的状态已经不能够解决这样带有多个变化的问题,于是在设计状态的时候考虑二维。个人认为在动态规划的思考中,状态的设计是最为核心的,也是最为难的,如果设计出一个好的状态能够事半功倍,整个转移的逻辑也能迅速出来。
做法如下:
状态:dp[i][j]表示完成了前i列的方格填充,并第i+1列有j个冗余的状态的方案数
转移方程:
dp[i][0] = dp[i-2][0] + dp[i-1][1] + dp[i-2][2];
dp[i][1] = dp[i-1][2]
dp[i][2] = dp[i-1][1] + dp[i-1][0]
根据这几个状态转移方程,问题就解决了。