トピックリンク:http://acm.hdu.edu.cn/showproblem.php?pid=4804
効果の対象に
あなたが得た(時間が\ mは\ N)\矩形領域の。あなたは使用する必要があります\(1 \回1 \)と\(2 \ 1 \回)レンガがこの領域をカバーし、そして満たす次の要件を:
- すべてのレンガは、縦置きまたは横を解放することができます。
- 角度レンガは、グリッド上に配置されたことを特徴とします。
- \(1 \回1 \)以上のブリック(C \)\ブロックも超える(D \)\ブロック、\(1 \ 2回\)レンガ無制限。
- 最初のいくつかの正方形は、これらのボックスは、任意のレンガでカバーすることができない、満たされています。(この入力ボックスに0で表される、箱は、一般的で表されます)
私はこれらの規則を満たすために、プログラムの種類がカバーされた矩形領域であってもよいどのように多くのだろうか?
問題解決のためのアイデア
輪郭動的プログラミングは、最初の状態に圧縮され、格子は今覆われ表し、0が覆われていない示し、そう輪郭が現在考え得ることを\(M \)整数列に圧縮し、その後、フォロー転送を置くためにどのようにどのようなレンガ、再生。
ステータス\(F [今] [S ] [K]は、\) を表し:現在の位置(今\(\)の行番号および列番号を描画することができるが、スクロールアレイを達成するために)、端部位置の不確定性の現在の状態を(\ S \) 、およびそれが置かれている\(K \)\(1 \回1 \)レンガ液の合計数。
輪郭線DP、回答された後に\(\ I sum_ {C} = ^ {D} F [今] [(M << 1)-1] [I] \)。
次のようにコードは次のとおりです。
#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1000000007LL;
int n, m, C, D;
long long f[2][1<<11][22];
char maze[101][11];
int main() {
while (~scanf("%d%d%d%d", &n, &m, &C, &D)) {
for (int i = 0; i < n; i ++) scanf("%s", maze[i]);
memset(f[0], 0, sizeof(f[0]));
int now = 0;
f[0][(1<<m)-1][0] = 1;
for (int i = 0; i < n; i ++) { // 遍历行号i
for (int j = 0; j < m; j ++) { // 遍历列号j
now = now ^ 1;
memset(f[now], 0, sizeof(f[now]));
for (int k = 0; k <= D; k ++) { // 遍历放置前已放置1x1砖块个数k
for (int s = 0; s < (1<<m); s ++) { // 遍历放置前不确定点状态
int s2, k2;
/** 当前格子不能放 */
if (maze[i][j] == '0') {
if (s & (1<<(m-1))) { // 最前面格子也放了
s2 = (s<<1)^1, k2 = k;
s2 &= (1<<m)-1;
f[now][s2][k2] += f[now^1][s][k];
f[now][s2][k2] %= MOD;
}
}
/** 当前格子可以放 */
else { // maze[i][j] == '1'
/** 情况1:当前格子不放 */
if (s & (1<<(m-1))) {
s2 = (s<<1), k2 = k;
s2 &= (1<<m)-1;
f[now][s2][k2] += f[now^1][s][k];
f[now][s2][k2] %= MOD;
}
/** 情况2:当前格子放一个竖着2x1的砖块 */
if (i > 0 && !(s & (1<<(m-1)))) {
s2 = (s<<1)^1, k2 = k;
s2 &= (1<<m)-1;
f[now][s2][k2] += f[now^1][s][k];
f[now][s2][k2] %= MOD;
}
/** 情况3:当前格子放一个横着1x2的砖块 */
if (j > 0 && !(s & 1) && (s & (1<<(m-1)))) {
s2 = (s<<1)^3, k2 = k;
s2 &= (1<<m)-1;
f[now][s2][k2] += f[now^1][s][k];
f[now][s2][k2] %= MOD;
}
/** 情况4:当前格子放一个1x1的砖块 */
if ( k < D && (s & (1<<(m-1))) ) {
s2 = (s<<1)^1, k2 = k+1;
s2 &= (1<<m)-1;
f[now][s2][k2] += f[now^1][s][k];
f[now][s2][k2] %= MOD;
}
}
}
}
}
}
long long ans = 0;
for (int i = C; i <= D; i ++) {
ans = (ans + f[now][(1<<m)-1][i]) % MOD;
}
printf("%lld\n", ans);
}
return 0;
}