矩形覆盖:最直观的想法是,经典斐波拉契数列变形,递推公式为f(n)=f(n-1)+f(n-2)。接下来分别使用四种方法实现:递归、记忆化搜索、动态规划、滚动数组。其整体思路为:1个2*1的小矩形覆盖一个2*1的大矩形有一种方法,2个2*1的小矩形覆盖一个2*2的大矩形有两种方法,n个2*1的小矩形覆盖一个2*n的大矩形可以是:第一个小矩形竖着,那么其他的有n-1个;第一个小矩形横着,那么必定第二个也需要横着,那么其他的有n-2个。
int rectCover(int number) { if(number==0) return 0; // 1个2*1的小矩形覆盖一个2*1的大矩形有一种方法 if(number==1) return 1; // 2个2*1的小矩形覆盖一个2*2的大矩形有两种方法 if(number==2) return 2; // n个2*1的小矩形覆盖一个2*n的大矩形可以是:第一个小矩形竖着,那么其他的有n-1个;第一个小矩形横着,那么必定第二个也需要横着,那么其他的有n-2个 return rectCover(number-1)+rectCover(number-2); }
// 0<=n<=38 int memo[40]={0}; int rectCover(int number) { if(number==0) return 0; // 1个2*1的小矩形覆盖一个2*1的大矩形有一种方法 if(number==1) return 1; // 2个2*1的小矩形覆盖一个2*2的大矩形有两种方法 if(number==2) return 2; if(memo[number]!=0) return memo[number]; // n个2*1的小矩形覆盖一个2*n的大矩形可以是:第一个小矩形竖着,那么其他的有n-1个;第一个小矩形横着,那么必定第二个也需要横着,那么其他的有n-2个 return memo[number]=rectCover(number-1)+rectCover(number-2); }
int rectCover(int number) { vector<int> dp(number+1,0); dp[0]=0; // 1个2*1的小矩形覆盖一个2*1的大矩形有一种方法 dp[1]=1; // 2个2*1的小矩形覆盖一个2*2的大矩形有两种方法 dp[2]=2; for(int i=3;i<=number;i++) // n个2*1的小矩形覆盖一个2*n的大矩形可以是:第一个小矩形竖着,那么其他的有n-1个;第一个小矩形横着,那么必定第二个也需要横着,那么其他的有n-2个 dp[i]=dp[i-1]+dp[i-2]; return dp[number]; }
int rectCover(int number) { if(number==0) return 0; if(number==1) return 1; if(number==2) return 2; // 1个2*1的小矩形覆盖一个2*1的大矩形有一种方法 int a=1; // 2个2*1的小矩形覆盖一个2*2的大矩形有两种方法 int b=2; int c; for(int i=3;i<=number;i++) { // n个2*1的小矩形覆盖一个2*n的大矩形可以是:第一个小矩形竖着,那么其他的有n-1个;第一个小矩形横着,那么必定第二个也需要横着,那么其他的有n-2个 c=a+b; a=b; b=c; } return c; }