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;

}

你可能感兴趣的:(integrate)