标签:
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
一个大矩形
覆盖的方法数
设 被n个2*1的小矩形无重叠地覆盖的方法总数为 f(n)
当n=1时,明显f(1)=1;
当n=2时,只能两个都横着或两个都竖着放,有f(2)=2;
当小矩形个数为n,来覆盖这个2*n的大矩形。第一步只有两种放法:
①竖着放,那么剩下的摆放总数为 f(n-1)
②横着放,那么剩下的摆放总数为 f(n-2)。因为它下面的那块也跟随着它的摆放而确定(必须是一个横着放的小矩形)。
很容易看出满足斐波那契数列。
斐波那契数列(Fibonacci sequence),又称黄金分割数列
在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*)
指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……
可以得出递推公式:
| 1 (n=0 )
f(n) = | 1 (n=1 )
| f(n-1)+f(n-2) (n>=2)
解法一 (递归) 运行时间:924ms 占用内存:654k
public class Solution {
public int RectCover(int target) {
if(target<=1) return 1;
return RectCover(target-1)+RectCover(target-2);
}
}
递归效率不高,重复计算多,比如:
f(4) = f(3) + f(2);
= f(2) + f(1) + f(1) + f(0);
= f(1) + f(0) + f(1) + f(1) + f(0);
求f(4)就要计算三次f(1)和两次f(0),显然这是不行的。
解法二(动态规划) 运行时间:29ms 占用内存:629k
public class Solution {
public int RectCover(int target) {
if(target<=1) return 1;
int i =1;//f(0)
int j =1;//f(1)
for(;target>=2;target--){
j+=i;
i=j-i;
}
return j;
}
}
显然这个快很多,n>=2时,根据 f(n)=f(n-1)+f(n-2)进行依次计算,最后得出 f(target)并返回。
标签:
原文地址:http://blog.csdn.net/amazing7/article/details/51272179