您的位置:首页 > 其它

poj2411_Mondriaan's Dream_状压DP(插头)

2018-02-27 20:53 411 查看
题目大意用 1 * 2 的骨牌密铺 h * w 的方格

思路用k记录考虑第(i, j)时的复杂状态,k & (1 << (j - 1)) 为1时表示此时已被之前的操作所覆盖(来自 (i - 1, j) 或 (i, j - 1)),为0时未被覆盖三维dp数组,一直超时,降维后AC#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define INF 0x3f3f3f3f
#define rep0(i, n) for (int i = 0; i < n; i++)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)
#define rep_1(i, n) for (int i = n; i > 0; i--)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define mem(x, y) memset(x, y, sizeof(x))
#define MAXH 15

using namespace std;
typedef long long LL;
int h, w;
LL dp[MAXH][1 << MAXH];
void DP()
{
dp[0][0] = 1;
for (int i = 1; i <= h; i++)
{
if (i > 1)
for (int k = 0; k < (1 << w); k++)
dp[0][k] = dp[w][k];

for (int j = 1; j <= w; j++)
{
mem(dp[j], 0);
int up = 1 << (j - 1), r = 1 << j;
for (int k = 0; k < (1 << w); k++)
{
/**
当(i, j)已被覆盖时,(i, j + 1)不会被覆盖
当(i, j)被覆盖时,竖放后(i, j + 1)被覆盖
*/
dp[j][k ^ up] += dp[j - 1][k];

if ((k & up) == 0 && (k & r) == 0)
{
//考虑横放
dp[j][k ^ r] += dp[j - 1][k];

}

}
}
}
}

int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE

while (scanf("%d %d", &h, &w) != EOF && h && w)
{
mem(dp, 0);
DP();
printf("%lld\n", dp[w][0]);

}

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