从简单到复杂:理解动态规划通过矩形覆盖问题
动态规划是解决各种算法问题的一种强大方法,特别是当问题可以分解成重叠的子问题时。为了深入理解这个概念,我们将先从一个简单的矩形覆盖问题开始,然后逐步过渡到更复杂的二维棋盘覆盖问题。
简单问题:用2x1的小矩形覆盖2xn的大矩形
假设我们有无数个 2x1
的小矩形,我们想要用这些小矩形去覆盖一个 2xn
的大矩形。我们想知道有多少种不同的覆盖方式。
题目链接:矩形覆盖_牛客题霸_牛客网 (nowcoder.com)
解题思路
这个问题实际上是一个斐波那契数列问题。我们可以发现:
-
当
n=1
时,只有一种覆盖方式。 -
当
n=2
时,有两种覆盖方式。 -
对于
n>2
,考虑第一个小矩形的放置方式:如果横放,剩下的部分是2x(n-1)
的矩形;如果竖放,那么因为矩形的宽度是2,我们必须再竖放一个小矩形在旁边,剩下的部分是2x(n-2)
的矩形。因此,总的覆盖方式数f(n) = f(n-1) + f(n-2)
。
代码实现
public int rectCover(int n) {
if (n <= 1) return n;
int a = 1, b = 1;
for (int i = 2; i <= n; i++) {
int temp = a + b;
a = b;
b = temp;
}
return b;
}
这段代码使用了斐波那契数列的性质来求解问题,其中 a
和 b
分别存储了 f(n-2)
和 f(n-1)
的值。
复杂问题:棋盘覆盖问题
现在,让我们将问题扩展到二维。假设我们有一个 N x M
的棋盘,我们想用 1x2
的矩形以不重叠的方式完全覆盖整个棋盘。这个问题相较于之前的问题,增加了一个维度,使得问题变得更加复杂。
题目链接:291. 蒙德里安的梦想 - AcWing题库
理解动态规划
在深入问题之前,让我们先简单回顾一下动态规划的核心思想。动态规划是一种将问题分解为较小子问题&