题目来源:http://poj.org/problem?id=2411
★我一开始还以为是找规律的题(不过那时候我也没学 状压DP) 现在算是第二题吧
题意:
你有长宽为2 1 的矩形,问有多少种放法组成一个n*m的大矩形
思路:
把大矩形分为1*1的小正方形来看,然后每一行都会有m个单元最多11个,我们可以用二进制来表示每一行
然后每一层都只受他上一层的影响,而第一层我们可以枚举,然后就可以慢慢推出来了
dp[ i ][ j ] 指 前 i 层的 前 i-1 层放满且第i层状态为 j 的 方法数
当第i层 状态为 100001时 表示 第一个和第六个被占过了
所以下一层就从状态 011110 开始推
详见代码
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
const int maxn=1<<15;
const int mod=1e9+7;
typedef long long LL;
LL n,m,tmp;
LL dp[20][1<<15];
void hhh(int k,int x,int pos)
{
if(pos==m) {dp[k][x]+=tmp; return ;}
hhh(k,x,pos+1);
if(pos<=m-2&&!(x&1<<pos)&&!(x&(1<<pos+1)))
hhh(k,x|1<<pos|1<<pos+1,pos+2);
}
int main()
{
while(~scanf("%lld%lld",&n,&m)&&(n||m)){
memset(dp,0,sizeof dp);
tmp=1;
hhh(1,0,0);
for(int i=2;i<=n;i++){
for(int j=0;j<(1<<m);j++){
if(dp[i-1][j]) tmp=dp[i-1][j];
else continue;
hhh(i,~j&((1<<m)-1),0);
}
}
cout<<dp[n][(1<<m)-1]<<endl;
}
return 0;
}