您的位置:首页 > 其它

POJ 2411 Mondriaan's Dream 状态压缩 搜索

2012-08-06 17:23 561 查看
题意:

求用1 * 2 的矩行拼h * w的矩阵方法数(h,w <=11)

算法:

1.朴素算法,根据关系,枚举

由于在做第i行dp时必须完全覆盖第i-1行,只要抓住这个条件不放就行。

1、如果第i行中有0,则第i-1行一定为1;

2、如果第i行中为1的x列第i-1行为0,说明第i行肯定是竖着放的;

3、如果第i行中为1的x列第i-1行的该列也为1,可能性只有一个,第i行是横放的,所以第i行的x+1列也必须为1,又因为第i行的x+1列为1是因为横着放的,所以第i-1行的x+1列也必须为1。

View Code

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
__int64 dp[2][4100], cow;
/*
状态1表示放了,0表示没有放

1. 竖直放置 (上行该列状态为0,当前行该列状态为1)
2. 横着放置  上行该两列状态为1, 此行该两列状态为1
3. 不放  //上行该列状态为1,当前行该列状态为0

*/

void DFS( int c, int s1, int s2, int m) //s1当前行状态, s2上一行状态
{
if( c > m )
return;
if( c == m )
{
dp[cow%2][s1] += dp[(cow-1)%2][s2];
return;
}
DFS(c + 1, (s1<<1)|1, s2<<1, m ); //竖直放置
DFS(c + 1, s1<<1, s2<<1|1, m); //不放
DFS(c + 2, (s1<<2)|3, (s2<<2)|3, m);  //横着放置
}

void DFS_First(int c, int s1, int m)
{
if( c > m)
return;
if( c == m )
{
dp[1][s1]++;
return;
}
DFS_First(c + 1, s1<<1,  m); //不放
DFS_First(c + 2, (s1<<2)|3, m);  //横着放置

}

int main( )
{
int N, M;
while( scanf("%d%d",&N,&M), N && M)
{
if( (N * M) % 2 )
{
puts("0");
continue;
}
if( N > M )
swap(N, M);
memset(dp, 0, sizeof(dp));
DFS_First(0, 0, M);
for( cow = 2; cow <= N ; cow++)
{
DFS(0, 0, 0, M);
memset(dp[(cow-1)%2], 0, sizeof(dp[0]));
}
printf("%I64d\n", dp[N % 2][(1<<M) - 1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: