广场铺砖问题
Description
有一个
W
行
Input
只有一行
2
个整数,分别为
Output
只有 1 个整数,为所有的铺法数。
Sample Input
2 4
Sample Output
5
Solution
用
预处理两个状态之间的关系,即上下行之间的关系。然后用DP,统计可以达到当前行这样状态的数量。
Code
#include <iostream>
#include <cstdio>
#include <cstring>
#define LL long long
using namespace std;
LL cnt,w,h,MAXN,ans,oo;
bool can[5000][5000];
LL num[5000];
LL head[5000];
LL nxt[100000];
LL data[100000];
LL f[5000][20];
void add(LL x,LL y){
nxt[cnt]=head[x];data[cnt]=y;head[x]=cnt++;
}
void dfs(LL pre,LL step,LL now){
if(step==h){
if(!can[now][pre]){
can[now][pre]=true;
add(now,pre);
}
return;
}
if(pre&(1<<step)){
dfs(pre,step+1,now);
}
else{
dfs(pre,step+1,now|(1<<step));
if(!(pre&(1<<(step+1)))&&step<h-1)dfs(pre,step+2,now);
}
}
LL dp(LL x,LL y){
LL sum=0;
if(f[x][y]!=oo)return f[x][y];
if(y==0)return x==0?1:0;
for(LL i=head[x];i!=-1;i=nxt[i]){
LL tmp=dp(data[i],y-1);
sum+=tmp;
}
return f[x][y]=sum;
}
int main(){
freopen("floor.in","r",stdin);
freopen("floor.out","w",stdout);
memset(f,0x3f,sizeof f);oo=f[0][0];
memset(head,-1,sizeof head);
scanf("%lld%lld",&w,&h);MAXN=(1<<(h));
for(LL i=0;i<MAXN;i++)
dfs(i,0,0);
LL tmp=dp(0,w);
ans+=tmp;
printf("%lld\n",ans);
return 0;
}