zoukankan      html  css  js  c++  java
  • P2704 [NOI2001] 炮兵阵地

    原题连接

    • 题意:给出 (n leqslant)(m leqslant 10) 行的矩阵,要求出来,炮兵能打到横竖打两格,然后要求最多放多少个炮兵。
    • 题解:当发现尽管每行是 (2^m) 即最大是 (1024) 但是如果把限制加入,每行每个炮兵相邻不能小于 (2),所以预处理那么就会使得本来是 (1024) 变成 (64)
      有一种简单的方法判断是否是山地
      还有一种简单的方法判断敌人是否在一起。
    #include <iostream>
    #include <vector>
    using namespace std;
    const int N = 110;
    char mp[N][110];
    int G[N];
    vector<int>state;
    int n, m;
    int dp[2][N][N];
    void init() {
        for (int i = 0; i < (1 << m); i ++) {
            bool f = 1;
            for (int j = 0; j < m; j ++) {
                if (i >> j & 1 && (i >> j + 1 & 1 || i >> j + 2 & 1 )) {
                    f = 0;
                }
            }
            if (f)
            state.push_back(i);
        }
    }
    int cnt(int x) {
        int ret = 0;
        int X = x;
        while (x) {
            ret += x & 1;
            x /= 2;
        }
        return ret;
    }
    void solve() {
        cin >> n >> m;
        for (int i = 1; i <= n; i ++) {
            cin >> (mp[i]);
            for (int j = 0; j < m; j ++) {
                if (mp[i][j] == 'H')G[i] += 1 << j;
            }
        }
        init();
        int ans = -1;
        //cout << state.size() << endl;
        for (int i = 1; i <= n; i ++) {
            for (int ii = 0; ii < state.size(); ii++) {
                for (int jj = 0; jj < state.size(); jj++) {
                    for (int kk = 0; kk < state.size(); kk++) {
                        int a = state[ii], b = state[jj], c = state[kk];
                        if ( (a & b | b & c | a & c) ==0) {//炮兵们是否能攻击到
                            if ( (a & G[i] | b & G[i-1])  == 0) {//是否是合理放置
                                dp[i&1][ii][jj] = max(dp[i&1][ii][jj], dp[i-1&1][jj][kk] + cnt(a));
                                ans = max(ans, dp[i&1][ii][jj]);
                                // if (ans == 5){
                                //     cout << i << " " << a << " " << b << " " << c << "?" << (b&c) << endl;
                                //     cout << (a&b) << endl;
                                //     cout << (a&c) << endl;
                                //     cout << (b&c) << endl;
                                //     cout << (0|9) << endl;
                                //     cout << ((a & b) | (b & c) | (a & c)) << endl;
                                // }
                            }
                        }
                    }
                }
            }
        }
        cout << ans << endl;
    }
    int main() {
        int t = 1;//cin >> t;
        while (t--)solve();
        return 0;
    }
    
  • 相关阅读:
    poj2502(最短路)
    poj1511(最小环和)
    uva11090(spfa判负环)
    hdu4370(spfa最短路最小环)
    uva10561(SG)
    uvalive5059(SG)
    uvaliva3905(扫描线)
    scu4445(模拟)
    uvalive3902(树上的最优化 贪心)
    scu4444(完全图最短路)
  • 原文地址:https://www.cnblogs.com/Xiao-yan/p/14786000.html
Copyright © 2011-2022 走看看