POJ 1038 Bugs Integrated(状态压缩DP)

题意:

将 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;
}
posted @ 2013-04-05 19:43  kedebug  阅读(1200)  评论(0编辑  收藏  举报