您的位置:首页 > 其它

POJ 1038 Bugs Integrated(状态压缩DP)

2013-04-05 19:43 330 查看
题意:

将 2*3 的芯片嵌入 n*m 的单位尺寸模板中,模板上面有一些坏点将被标记出,求最大的芯片数量。

黑书 138 页的例题, CEOI 2002;

思路:

1. 由于 m <= 10,所以可以针对每一行看成一个整体,根据情况来产生一个状态,首先肯定是枚举当前行的状态,来产生下一行的状态了,时间复杂度为O(nm3m);

2. 递推的过程中,因为是由一个已知状态,转移到多个未知状态,如何产生这多个未知状态?这里采用 DFS 的方式,提供了 2 个数组 Q,随时存储和恢复状态;

3. Q[1][i] 代表当前行的摆放情况, Q[0][i] 代表上一行的摆放情况。并且值为 0,1,2 如黑书上面描述的一样。采用 3 进制表示法,因为如果用 2 个二进制位表示,总共可能会达到 20 位,这样会产生很大的内存浪费;

4. 因为当前行的状态以及值,都是由上一行的情况转移过来的,所以利用滚动数组,可以有效的节省内存,注意每次要置 -1 即可。

#include <iostream>
#include <algorithm>
using namespace std;

bool grid[160][12];
int row, col, Q[2][12], dp[2][60000];

void backstate(int s, int f[]) {
for (int i = 0; i < col; i++) {
f[i] = s % 3; s /= 3;
}
}

int getstate(int f[]) {
int ans = 0;
for (int i = col-1; i >= 0; i--) {
ans *= 3;
ans += f[i];
}
return ans;
}

int T1, T2;

void dfs(int i, int count, int state) {
if (i > col - 1)
return;

if (i+2 < col && Q[1][i] == 0 && Q[1][i+1] == 0 && Q[1][i+2] == 0) {
Q[1][i] = Q[1][i+1] = Q[1][i+2] = 2;
int now = getstate(Q[1]);
dp[T2][now] = max(dp[T2][now], count+1);
dfs(i+3, count+1, now);
Q[1][i] = Q[1][i+1] = Q[1][i+2] = 0;
}

if (i+1 < col && Q[1][i] == 0 && Q[1][i+1] == 0 && Q[0][i] == 0 && Q[0][i+1] == 0) {
Q[1][i] = Q[1][i+1] = 2;
int now = getstate(Q[1]);
dp[T2][now] = max(dp[T2][now], count+1);
dfs(i+2, count+1, now);
Q[1][i] = Q[1][i+1] = 0;
}

dp[T2][state] = max(dp[T2][state], dp[T1][getstate(Q[0])]);
dfs(i+1, count, state);
}

int solvedp() {
int endstate = 1;
for (int i = 0; i < col; i++)
endstate *= 3;

for (int i = 0; i < col; i++)
Q[1][i] = grid[0][i] ? 2 : 1;
memset(dp[0], -1, sizeof(dp[0]));
dp[0][getstate(Q[1])] = 0;

T1 = 1, T2 = 0;
for (int i = 1; i < row; i++) {
T1 ^= 1, T2 ^= 1;
memset(dp[T2], -1, sizeof(dp[0]));
for (int s = 0; s < endstate; s++) {
if (dp[T1][s] == -1)
continue;
backstate(s, Q[0]);
for (int j = 0; j < col; j++) {
Q[1][j] = grid[i][j] ? 2 : Q[0][j]-1;
if (Q[1][j] < 0) Q[1][j] = 0;
}
dfs(0, dp[T1][s], getstate(Q[1]));
}
}
int ans = -1;
for (int s = 0; s < endstate; s++)
ans = max(ans, dp[T2][s]);
return ans;
}

int main() {
int cases;
scanf("%d", &cases);
while (cases--) {
int tag;
scanf("%d%d%d", &row, &col, &tag);
memset(grid, false, sizeof(grid));
for (int i = 0; i < tag; i++) {
int x, y;
scanf("%d%d", &x, &y);
grid[x-1][y-1] = true;
}
printf("%d\n", solvedp());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: