【发布时间】:2013-09-03 02:02:40
【问题描述】:
我正在尝试在SPOJ GNY07H 上解决这个问题: 问题是:
我们希望平铺一个 4 个单位高、N 个单位长的网格,其中包含 2 个单位乘一个单位的矩形(多米诺骨牌)(在任一方向上)。
编写一个程序,将网格的宽度 W 作为输入,并输出平铺 4×W 网格的不同方法的数量。
输入: 2 3 7
输出: 5 11 781
我知道这是一个位掩码动态编程问题。 但是,我的方法没有得到正确的输出。谁能指出我的方法中的错误。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <climits>
using namespace std;
int dp[16][4][60];
int solve(int mask, int d, int t)
{
if(t > 4) return 0;
if(d == 0) return mask == 0;
if(t == 4) return solve(mask, d-1, 0);
int &ret = dp[mask][t][d];
if(ret != -1)
return ret;
ret = 0;
ret += solve(mask|(1<<t), d, t+1) + solve(mask, d, t+2);
return ret;
}
int main()
{
int i, j, k, l, n, w;
scanf("%d", &n);
while(n--)
{
memset(dp, -1, sizeof(dp));
scanf("%d", &w);
int ans = solve(0, w, 0);
printf("%d\n", ans);
}
return 0;
}
该方法的工作原理如下:
我一行一行地工作。在每一行,对于一列,我尝试先水平和垂直放置瓷砖。 mask 属性告诉行+1 中哪些列已经被填充。因此,当 tile 水平放置在行中时,mask = mask | (1 t)) 用于第 1 行,否则保持不变。我以这种方式计算可能性的总数。递归的停止条件是当行(在程序中为 d)时掩码为 0,即行变为 0。当所有此级别的列已填满。
【问题讨论】:
-
你能花几分钟解释一下这应该做什么吗?链接不会永远存在。