Time Limit:1000MS | Memory Limit:65535KB | 64bit IO Format:%lld & %llu |
Description
由于方老师出色的专题讲座,他的名气迅速扩散到全国各地,并通过各地的讲座赚到了很多钱,鉴于现在盛行买表,于是方老师带上了一个 H×W 的盒子去买表,我们假设每一个表占 1×2 或者 2×1 的空间,问方老师有多少种放置表的方式,把这个盒子填满。
Input
输入有多组数据
每组数据占一行,每一行有 2 个正整数 H,W,(1≤H,W≤11)
Output
对于每组测试数据输出 1 个整数,表示该测试数据的答案
Sample Input
2 10 3 3
Sample Output
89 0
Hint
Source
2014 UESTC Training for Dynamic Programming
解析
状态压缩DP入门题。类似于HDU1992 Tiling a Grid With Dominoes可以看我的另一篇博客 http://blog.csdn.net/liao_jingyi/article/details/40632695
我用的是压缩每一列的状态
注意结束状态必须是1 1 1 1 1 1……1 == (1<<W)-1 (因为不能再向后扩展了)
解析
状态压缩DP入门题。类似于HDU1992 Tiling a Grid With Dominoes可以看我的另一篇博客 http://blog.csdn.net/liao_jingyi/article/details/40632695
我用的是压缩每一列的状态
注意结束状态必须是1 1 1 1 1 1……1 == (1<<W)-1 (因为不能再向后扩展了)
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
long long f[12][1<<11],H,L;
bool legal[1<<11];
bool check(int x)
{
//0表示待扩展状态 1表示结束状态
for(int i=1;i<(1<<H);i=i<<1)
if(x&i)
{
if(i<<1<(1<<H) && x&(i<<1)) i=i<<1;
else return 0;
}
return 1;
}
void DP()
{
memset(f,0,sizeof(f));
memset(legal,0,sizeof(legal));
for(int i=0;i<(1<<H);i++)
if(check(i)) {f[1][i]=1; legal[i]=1;}
for(int i=2;i<=L;i++)//枚举列
for(int j=0;j<(1<<H);j++)//枚举上一列状态
if(f[i-1][j])
for(int k=0;k<(1<<H);k++)//枚举当前列状态
if(legal[j&k] && (j|k)==(1<<H)-1) f[i][k]+=f[i-1][j];
printf("%lld\n",f[L][(1<<H)-1]);
}
int main()
{
while(scanf("%lld%lld",&H,&L)==2)
{
if(H>L) swap(H,L);//交换一下保证H<L 可以提高效率
DP();
}
return 0;
}