刷题11 矩形覆盖问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了刷题11 矩形覆盖问题相关的知识,希望对你有一定的参考价值。

描述:  我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

 

思路: 这种题开始肯定要找规律, 看了看, n = 1时, 一种方法; n = 2时, 两种方法; n = 3时,三种方法; n = 4时, 五种方法; ... ; 很自然想起了斐波那契数列。

证明一下: 

设 n 列一共有 f(n) 种无重叠的覆盖方法,先上一个自己画的图方便理解。

技术分享图片

1、对于n > 2的情况:首先我们可以知道小矩形是2 * 1,整个矩形为2 * n,所以我们在填充的时候只有横着填充跟竖着填充。 所以思路就是将从第1列填充到第n列的情况分解.

怎么分解呢,然后我又画了下面这个图, 方便理解。

技术分享图片

我想求从A到G总共多少中走法,咋求呢?   我先分解, 在第一步我有两种走法, 要么走B要么走C,然后B往后又有两种走法,C往后又有...

 

所以,说这么多,对于矩形填充所有情况, 那么先走第一步, 两种情况:竖着放或者横着放。 

(1)对于第一步竖着放:  直接占据一竖列就OK了, 然后还剩下 n-1 列, 而n-1 列有 f(n-1) 种填充方法, 所以第一步竖着放总共有 1 * f(n-1) = f(n-1) 种方法;

(2)对于第一步横着放:  先放一个 2 * 1 小矩形,让它占据第一行第一、二列, 此时还剩下 n-2 列加上一个第二行第一、二列的区域。 我们难以用科学的方法表示出来, 怎么办?那就继续分解。

对于第二行第一、二列的区域,我们只存在唯一方式就是横着放上小矩形, 这样操作之后还剩下 n-2 列有 f(n-2) 种填充方法, 所以第一步横着放总共有 1 * 1 * f(n-2) = f(n-2) 种方法。

那么好了, 将这两个合并就是n列一共的方法数了, 即 f(n-1) + f(n-2) = f(n) 。看到这个式子是不是很熟, 对, 斐波那契数列。

2、那好,现在考虑到 n = 2 的情况, 不用 f(n-1) + f(n-2) = f(n) 这个公式, 更不要直接穷举, 用1中的思想考虑,可以得到:  f(2) = 1 + 1 * 1 = 2 。

 那现在可以写代码了:

 1 class Solution {
 2 public:
 3     int rectCover(int number) {
 4         if(number < 3)
 5             return number;
 6         int first = 1;
 7         int second = 2;
 8         for(int i = 3; i <= number; i++)
 9         {
10             second = first + second;
11             first = second - first;
12         }
13         return second;
14     }
15 };

 

 

顺便想一下, 假如用 3 * 1 的小矩形填充 3 * n 的大矩形呢?

我们还是用 f(n) 表示 n 列的所有方法,第一步还是分两种情况:

(1)横着放:  横着放占了三列, 剩下 n-3 列, 总共情况为 1 * 1 * f(n-3) = f(n-3)

(2)竖着放: 竖着放了一列, 剩下 n-1 列, 总共情况为 1 * f(n-1) = f(n-1)

所以 f(n) = f(n-1) + f(n-3)

 

接下来还有其他变形都OK了。

以上是关于刷题11 矩形覆盖问题的主要内容,如果未能解决你的问题,请参考以下文章

牛客(11)矩形覆盖

java刷题--84柱状图中最大的矩形

小矩形覆盖大矩形问题

小矩形覆盖大矩形问题

剑指Offer系列之题11~题15

poj-1151矩形面积并-线段树