第二道状态压缩dp,比poj1185简单点,调试费了不少时间,发现现在写程序的缺点在于不够精简,又臭又长。
//============================================================================================
//
// > File : poj2411.cpp
// > Author : flowertree
// > Time : 2015年12月25日
// > Algorithm : 状态压缩DP 铺满问题
// : 状态压缩一般规模较小 M * N 的方格 一般
// : M 和 N 不超过15 因为复杂度最大为 M ^ N
// : 有剪枝的话复杂度降下来 但不适用大规模数据
//
//=============================================================================================
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
#define M 13
#define MAX 1 << 11
long long block[MAX];
long long dp[M][MAX];
int top;
int h, m;
void swap(int & a, int & b)
{
int temp = a;
a = b;
b = temp;
}
int CountBit(int x)
{
int sum = 0;
while(x != 0)
{
x = x & (x - 1);
sum++;
}
return sum;
}
void Init(int n) //每一行可能状态枚举储存
{
memset(block, 0, sizeof(block));
top = 0;
for(int i = 0; i < (1 << m); i++)
block[++top] = i;
}
bool isok(int a, int b) //判断两个状态是否共同成立 b是上一个状态
{
for(int i = (1 << (m - 1)); i != 0; i = i >> 1)
{
if(i == 1)
{
if(((block[a] & i) == 1))
{
if((block[b] & i) == 1)
return false;
}
else
{
if((block[b] & i) == 0)
return false;
}
break;
}
int temp = i >> 1;
if((block[a] & i) != 0)
{
if((block[b] & i) == 0)
continue;
else if(((block[a] & temp) == 0) || ((block[b] & temp) == 0))
return false;
i = i >> 1;
}
else
{
if((block[b] & i) == 0)
return false;
}
}
return true;
}
int main()
{
while(cin >> h >> m, h || m)
{
if((h * m) % 2 == 1)
{
cout << 0 << endl;
continue;
}
if(h < m)
swap(h, m);
Init(m);
//初始化第一行状态
memset(dp, 0, sizeof(dp));
bool mark;
for(int i = 1; i <= top; i++)
{
if(CountBit(block[i]) % 2 == 1)
continue;
mark = true;
for(int j = (1 << (m - 1)); j != 0; j = j >> 1)//检查第一行是否合适
{
if(j == 1)
{
if((j & block[i]) == 1)
mark = false;
break;
}
int temp = j >> 1;
if((j & block[i]) != 0)
{
if((temp & block[i]) != 0)
j = j >> 1;
else
{
mark = false;
break;
}
}
}
if(mark)
dp[1][i] = 1;
}
//后面的状态
for(int i = 2; i <= h; i++)
{
for(int j = 1; j <= top; j++)
{
for(int k = 1; k <= top; k++)
{
if(dp[i - 1][k] != 0)
{
if(isok(j, k))
{
dp[i][j] += dp[i - 1][k];
}
}
}
}
}
cout << dp[h][top] << endl;
}
system("pause");
return 0;
}