【ACWing】292. Artillery position

Subject address:

https://www.acwing.com/problem/content/294/

Command generals intend to N * MN * MNM deployed their artillery troops on the grid map. OneN ∗ MN*MNMap of M byNNN lineMMIt is composed of M columns. Each grid of the map may be a mountain ('H'indicated by) or a plain ('P'indicated by), as shown in the figure below. At most one artillery unit can be deployed on each plain terrain (artillery units cannot be deployed on mountainous terrain); the attack range of an artillery unit on the map is its four directions2 22 grids or less. If an artillery unit is deployed on the plain marked by gray in the map, the black grid in the figure indicates the area it can attack: two squares in the horizontal direction and two squares in the vertical direction. None of the other white grids on the map can be attacked. It can be seen from the picture that the attack range of the artillery is not affected by the terrain. Now, the generals plan how to deploy artillery units, under the premise of preventing accidental injury (ensure that no two artillery units can attack each other, that is, any artillery unit is not within the attack range of other artillery units), in the entire map The maximum number of artillery units of our army can be placed in the area.

Input format: The
first line contains two positive integers separated by spaces, representing NN respectivelyN andMMM ; NextNNN lines, each line contains continuousMMM characters ('P'or'H'), no spaces in between. Represents the data of each row in the map in order.

Output format:
only one line, containing an integer KKK represents the maximum number of artillery units that can be placed.

Data range:
N ≤ 100, M ≤ 10 N ≤ 100, M ≤ 10N100,M10

The idea is dynamic programming, you can use state compression to store the artillery release status of each line, that is, use an integer binary bit to store, 1 11 means artillery,0 00 means no artillery. Letf [i] [j] [k] f[i][j][k]f [ i ] [ j ] [ k ] is only the frontiiLine i , thi-1 i-1iThe status of line 1 isjjj ,iiThe status of row i iskkIn the case of k , how many artillery can be deployed at most. Then you can follow thei − 2 i-2iHow to put the 2 lines to classify, there are: f [i] [j] [k] = max ⁡ p ∧ j {f [i − 1] [p] [j] + c (k)} f[i ][j][k]=\max_{p\land j}\{f[i-1][p][j]+c(k)\}f[i][j][k]=pjmax{ f[i1][p][j]+c ( k ) ) wherec (k) c(k)c ( k ) iskkIn the binary representation of k ,1 1The number of 1 , andppp traverse all andjjj Legal status without contradiction. You can preprocess the legal status of all rows first, and preprocess each status1 1The number of 1 . Space can be optimized with a rolling array. code show as below:

#include <iostream>
#include <vector>
using namespace std;

const int N = 11, M = 1 << 10;
int n, m;
// 存输入,g[i]的各个二进制位表示第i行的地理情况,1表示有山,0表示无山
int g[110];
// 存行的合法状态
vector<int> state;
int f[2][M][M];
int cnt[M];

// 判断st是否是行合法状态
bool check(int st) {
    
    
    for (int i = 0; i < m; i++)
        if ((st >> i & 1) && ((st >> i + 1 & 1) || (st >> i + 2 & 1)))
            return false;
    return true;
}

// 存st的二进制表示里有多少个1
int count(int st) {
    
    
    int res = 0;
    while (st) {
    
    
        st -= st & -st;
        res++;
    }

    return res;
}

int main() {
    
    
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 0; j < m; j++) {
    
    
            char x;
            cin >> x;
            if (x == 'H') g[i] += 1 << j;
        }
    
    for (int i = 0; i < 1 << m; i++)
        if (check(i)) {
    
    
            state.push_back(i);
            cnt[i] = count(i);
        }

    for (int i = 1; i <= n; i++)
        for (int j = 0; j < state.size(); j++)
            for (int k = 0; k < state.size(); k++)
                for (int u = 0; u < state.size(); u++) {
    
    
                	// 如果在枚举第1行,那么此时前两行必须全是0才有意义
                    if (i == 1 && u != 0 && j != 0) continue;
                    
                    int a = state[j], b = state[k], c = state[u];
                    // 如果两行之间有冲突,则略过
                    if ((a & b) | (b & c) | (a & c)) continue;
                    // 炮兵放在山上的情形略过
                    if (g[i - 1] & a | g[i] & b) continue;
                    f[i & 1][j][k] = max(f[i & 1][j][k], f[i - 1 & 1][u][j] + cnt[b]);
                }

    int res = 0;
    for (int j = 0; j < state.size(); j++)
        for (int k = 0; k < state.size(); k++)
            res = max(res, f[n & 1][j][k]);

    cout << res << endl;

    return 0;
}

Time complexity O (n 2 3 n) O(n2^{3n})O ( n 23 n ), but it is not so high in reality, because the number of valid states is much less than2 n 2^n2n , spaceO (n 2 2 n) O(n2^{2n})O ( n 22 n )

Guess you like

Origin blog.csdn.net/qq_46105170/article/details/114527461