zoukankan      html  css  js  c++  java
  • POJ 1185 炮兵阵地(状态压缩DP)

    题意:

    求最大的炮兵摆放数量,并且使他们之间不相互误伤。

    NOI 01 的题目。

    思路:

    1. 和 POJ 1038 类似,把行看成是一个整体,每一种摆放代表着一种状态,r-2, r-1 行的状态决定着 r 行的状态;

    2. 本题状态比较稀疏,所以提前处理下炮兵的摆放无意是比较好的选择,由于没两个炮兵之间至少相距为 2,利用这个把每一行的炮兵可能摆放情况存放起来;

    3. dp[r][i][j] 表示第 r 行的状态为 i 且第 r-1 行的状态为 j 时,所能摆放的最大炮兵数量,同时还需要枚举 r-2 行的炮兵摆放情况;

    4. 最终有状态转移方程: dp[r][i][j] = max(dp[r][i][j], dp[r-1][j][k] + men[i]); 并且要求 dp[r-1][j][k] 存在,且 r 行能保证能摆放 i 状态;

    5. 有了 POJ 1038 和 POJ 1185 的积累,我想以后做此类基于摆放的状态压缩 DP 应该能够有个比较清晰的思路了。

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    int row, col;
    int state[60], cnt, men[60], mapstate[110];
    bool grid[110][12];
    int dp[2][60][60];
    
    bool judge(int s) {
        if (s & (s<<1))
            return false;
        if (s & (s<<2))
            return false;
        return true;
    }
    
    int calcmen(int s) {
        int ans = 0;
        while (s) {
            ans += 1;
            s &= (s-1);
        }
        return ans;
    }
    
    void initstate(int endstate) {
        cnt = 0;
        for (int s = 0; s < endstate; s++) {
            if (judge(s)) {
                state[cnt] = s;
                men[cnt] = calcmen(s);
                cnt += 1;
            }
        }
    }
    
    int solvedp() {
        memset(dp[0], -1, sizeof(dp[0]));
        for (int i = 0; i < cnt; i++) {
            if (mapstate[0] & state[i])
                continue;
            dp[0][i][0] = men[i];
        }
        int T1 = 1, T2 = 0;
        for (int r = 1; r < row; r++) {
            T1 ^= 1, T2 ^= 1;
            memset(dp[T2], -1, sizeof(dp[0]));
            for (int i = 0; i < cnt; i++) {
                if (state[i] & mapstate[r]) 
                    continue;
                for (int j = 0; j < cnt; j++) {
                    if ((state[i] & state[j]) || (state[j] & mapstate[r-1]))
                        continue;
                    for (int k = 0; k < cnt; k++) {
                        if ((state[i] & state[k]) || (state[k] & state[j]))
                            continue;
                        if (dp[T1][j][k] != -1)
                            dp[T2][i][j] = max(dp[T2][i][j], dp[T1][j][k]+men[i]);
                    }
                }
            }
        }
        int ans = -1;
        for (int i = 0; i < cnt; i++)
            for (int j = 0; j < cnt; j++)
                ans = max(ans, dp[T2][i][j]);
        return ans;
    }
    
    int main() {
        scanf("%d%d", &row, &col);
        for (int i = 0; i < row; i++) {
            char s[20];
            scanf("%s", s);
            mapstate[i] = 0;
            for (int j = 0; j < col; j++) {
                mapstate[i] <<= 1;
                mapstate[i] |= s[j] == 'H' ? 1 : 0;
            }
        }
        initstate(1<<col);
        printf("%d\n", solvedp());
        return 0;
    }
    -------------------------------------------------------

    kedebug

    Department of Computer Science and Engineering,

    Shanghai Jiao Tong University

    E-mail: kedebug0@gmail.com

    GitHub: http://github.com/kedebug

    -------------------------------------------------------

  • 相关阅读:
    altas(ajax)控件(十七):互斥复选框控件MutuallyExclusiveCheckBox
    JAVA处理Clob大对象
    JNI简介及实例
    《JavaScript凌厉开发 Ext详解与实践》的目录
    《JavaScript凌厉开发 Ext详解与实践》的可以预订了
    Quartz入门到精通
    《JavaScript凌厉开发 Ext详解与实践》作者简介与媒体推荐
    计院生活第二章 深入虎穴(下)
    IT行业简历模板及就业秘籍
    计院生活第二章 深入虎穴(上)
  • 原文地址:https://www.cnblogs.com/kedebug/p/3001642.html
Copyright © 2011-2022 走看看