Problem:Tiling
Description:题目意思很简单,给你一个2 * n的 长方形,让你用2 * 1的长方形和2 * 2的正方形去填,问有多少种方式可以正好填满。
Solution:首先分析可以知道n=1时,有一种方式可以填满;当n=2时,有3种方式;然后分析n=4时,如果最后一个格子用 2 * 1来填充的话,剩下的则可以看成是一个n=3的问题,如果最后一个用2 * 2来填充的话,有两种填充方式,一种是用两个2 * 1的横着来填充(不能竖着填充),另一种是用一个2 * 2的来填充,那么问题就可以看成是一个n=2的问题,所以n=4时有5种方式。推广到n可以得到一个递归方程f(n)=f(n-1)+2 * f(n-2);用递归的方法要注意记忆化搜索,不然会超时;用递推的话就不用考虑这个。
Code(C++)(递归实现):
#include <iostream>
#include <cstring>
using namespace std;
int dp[255][1000];
int used[255];
void f(int x,int ans[])
{
if(used[x]){
for(int i=0;i<1000;i++)
ans[i]=dp[x][i];
return ;
}
used[x]=1;
int a[1000],b[1000],c[1000];
int i,r=0;
for(int i=0;i<1000;i++)
{
a[i]=0;
b[i]=0;
c[i]=0;
}
if(x==0||x==1)
c[0]=1;
else if(x==2)
c[0]=3;
else
{
f(x-1,a);
f(x-2,b);
for(i=0;i<1000;i++)
{
c[i]=b[i]+b[i]+a[i]+r;
r=0;
if(c[i]>=10)
r=c[i]/10;
c[i]=c[i]%10;
}
}
for(i=0;i<1000;i++)
dp[x][i]=c[i];
}
void init()
{
int ans[1000];
for(int i=0;i<251;i++)
f(i,ans);
}
int main()
{
init();
int n,i;
int ans[1000];
while(cin>>n)
{
for(i=999;i>=0&&dp[n][i]==0;i--);
for(;i>=0;i--)
cout<<dp[n][i];
cout<<endl;
}
return 0;
}