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;
}
原文地址:https://www.cnblogs.com/Xiao-yan/p/14786000.html