铺砖块
写了一个多小时才给它写出来...(呜呜呜
首先,因为一块砖占两个格,所以总格数是单数的话就怎么都铺不满。直接输出 \(0\) 即可。
然后考虑状压 dp 。设 \(f[i][j]\) 表示前 \(i\) 行都放满且对第 \(i+1\) 行影响为 \(j\) 时的方案总数。
设数组 \(f1[j],f2[j]\) 表示第 \(j\) 种情况由状态 \(f1[j]\) 可以转移到 \(f2[j]\) 的状态。
则状态转移方程为 f[i][f2[j]]+=f[i-1][f1[j]];
。
最后再考虑怎么预处理。可以分三种情况讨论:
-
如果上一行对当前格子的影响为 \(1\) 也就是上面已经有砖块了,那么这里就不放,且对下一行的影响为 \(0\) 。
-
如果上一行对当前格子的影响为 \(0\) ,那么我们可以选择竖着放一块,对下一行的影响为 \(1\) 。
-
对于上种情况也可以横着放一个,对下一行没有影响,但记得 \(p\) 要一次性加上 \(2\) 。(刚才写的时候这里踩坑了qaq)
#include<bits/stdc++.h>
using namespace std;
int f[12][1<<12],f1[20001],f2[20001];
int m,n,cnt;
void dfs(int p,int st,int ed)
{
if(p==m)
{
cnt++;
f1[cnt]=st;f2[cnt]=ed;
return;
}
if(p>m) return;
dfs(p+1,(st<<1)+1,(ed<<1));
dfs(p+1,(st<<1),(ed<<1)+1);
dfs(p+2,(st<<2),(ed<<2));
return;
}
int main()
{
while(scanf("%d%d",&n,&m))
{
if(n==0&&m==0) break;
cnt=0;
memset(f,0,sizeof(f));
dfs(0,0,0);
f[0][0]=1;
if(m*n%2)
{
cout<<"0"<<endl;
continue;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=cnt;j++)
{
f[i][f2[j]]+=f[i-1][f1[j]];
}
}
cout<<f[n][0]<<endl;
}
return 0;
}
本文来自博客园,作者:樱雪喵,转载请注明原文链接:https://www.cnblogs.com/ying-xue/p/pu-zhuan-kuai.html