您的位置:首页 > 其它

POJ 2411 Mondriaan's Dream (状压DP,骨牌覆盖,经典)

2015-10-08 10:53 113 查看
题意:

  用一个2*1的骨牌来覆盖一个n*m的矩形,问有多少种方案?(1<=n,m<=11)

  

//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <deque>
#include <map>
#include <algorithm>
#include <vector>
#include <iostream>
#define pii pair<int,int>
#define INF 0x3f3f3f3f
#define LL long long
#define ULL unsigned long long
using namespace std;
const double PI  = acos(-1.0);
const int N=11;
LL dp[2][1<<11], cur;

LL cal(int n,int m)
{
if(n==m&&n%2==1)    return 0;
if(n<m) swap(n,m);
memset(dp[0],0,sizeof(dp[0]));
dp[cur=0][(1<<m)-1]=1;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
cur^=1;
memset(dp[cur],0,sizeof(dp[cur]));
int r=(1<<m)-1;
for(int  s=0; s<(1<<m); s++)
{
LL v=dp[cur^1][s];
if( (s&(1<<m-1))==0 )               //必须放竖
dp[cur][(s<<1)+1]+=v;
else
{
dp[cur][(s<<1)&r]+=v; //不放
if( j>1 && (s&1)==0 )          //放横
dp[cur][((s<<1)+3)&r]+=v;
}
}
}
}
return dp[cur][(1<<m)-1];
}

int main()
{
freopen("input.txt","r",stdin);
int n, m;
while(scanf("%d%d",&n,&m),n+m)
printf("%lld\n",cal(n,m));
return 0;
}


AC代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: