题目大意
用 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;
}