C++---compresión de estado dp---posición de artillería (un algoritmo por día 2023.4.17)

Nota:
Este tema es una pregunta aproximada titulada "State Compression dp-Mondrian's Dream" y "State Compression dp-Little King" y "State Compression dp-Cornfield" . Se recomienda leer y comprender estos tres artículos primero.

Tema:
Los generales en el comando planean desplegar sus unidades de artillería en un mapa de cuadrícula N×M.
Un mapa N × M consta de N filas y M columnas. Cada cuadrícula del mapa puede ser una montaña (indicada Hpor ) o una llanura ( Pindicada por ), como se muestra en la siguiente figura.

Se puede desplegar un máximo de una unidad de artillería en cada terreno llano (las unidades de artillería no se pueden desplegar en terreno montañoso); el rango de ataque de una unidad de artillería en el mapa se muestra en el área negra de la figura: si está marcado en gris en el
Por favor agregue una descripción de la imagen
map Despliega una unidad de artillería en la llanura, y la cuadrícula negra en la imagen indica el área que puede atacar: dos cuadrículas a la izquierda y derecha en dirección horizontal, y dos cuadrículas en dirección vertical y vertical.
Todas las demás cuadrículas blancas de la imagen no pueden ser atacadas.
Se puede ver en la figura que el rango de ataque de la artillería no se ve afectado por el terreno.

Ahora, los generales están planeando cómo desplegar las unidades de artillería, bajo la premisa de prevenir lesiones accidentales (para garantizar que dos unidades de artillería no puedan atacarse entre sí, es decir, que ninguna unidad de artillería esté dentro del rango de ataque de otras unidades de artillería). , en todo el mapa El número máximo de unidades de artillería de nuestro ejército que se pueden colocar en la zona.

Formato de entrada
La primera línea contiene dos números enteros positivos separados por espacios, que representan N y M respectivamente; las
siguientes N líneas contienen cada una M caracteres consecutivos (P o H) sin espacios entre ellos. Representa los datos de cada fila del mapa en orden.

Formato de salida
Solo una línea, incluido un número entero K, que indica el número máximo de unidades de artillería que se pueden colocar.

Rango de datos
N≤100, M≤10

输入:
5 4
PHPP
PPHH
PPPP
PHPP
PHHP
输出:
6

#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

const int N = 110, M = 1 << 10;
int n, m, cnt[M], st[N], f[2][M][M];
char t;
vector<int> state, state_trans[M];


bool check(int s) {
    
         //判断同一行中,三格内只能同时存在一个1,也就是炮兵不能互相攻击到为合法状态,
    for (int i = 0; i<m; i++) {
    
    
        if ((s >> i & 1) && ((s >> (i+1) & 1) | (s >> (i+2) & 1))) return false;
    }
    return true;
}
int count(int s) {
    
          //计算当前状态中1的数量
    int res = 0;
    for (int i = 0; i<m; i++) res += (s >> i & 1);
    return res;
}

int main() {
    
    
    cin >> n >> m;

    //预处理所有读入,将每一行的地势转换为二进制,1为山地,0为平原
    for (int i = 1; i<=n; i++) {
    
    
        for (int j = 0; j<m; j++) {
    
    
            cin >> t;
            st[i] += ((t=='H') << j);
        }
    }

    //预处理所有合法状态
    for (int i = 0; i < (1 << m); i++) {
    
    
        if (check(i)) {
    
    
            state.push_back(i);
            cnt[i] = count(i);
        }
    }

    //预处理所有合法状态转移, 本题行与行之间的限制就是不能在同一列摆放炮兵
    for (auto &a : state) {
    
    
        for (auto &b : state) {
    
    
            if ((a&b)==0) state_trans[a].push_back(b);
        }
    }

    //dp
    for (int i = 1; i<=n+2; i++) {
    
              //枚举地图的每一行,
        for (auto &a : state) {
    
           //枚举所有合法状态a(第i层)
            if ((a & st[i])==0) {
    
               //当状态a没有在山地上部署的炮兵,那就可以进行状态转移,=
                for (auto &b : state_trans[a]) {
    
            //枚举所有能从a转移到的状态b,(第i-1层)
                    for (auto &c : state_trans[b]) {
    
        //枚举所有能从b转移到的状态c,(第i-2层)
                        if ((a&c)==0) {
    
                 //a能转移到b,b能转移到c,但不代表a能转移到c(比如a=010,b=001,c=110,a-b合法,b-c合法,a-c不合法)
                            f[i&1][a][b] = max(f[i&1][a][b], f[(i-1)&1][b][c] + cnt[a]);
                        }
                    }
                }
            }
        }
    }

    //这里还是和之前的状压dp一样,n+2是小优化,表示:前n+2行已经摆完,且第n+2行状态为0(一个炮兵不摆),第n+1行状态为0,
    //那么就和sum(f[n][1~m][1~m])的方案数是一样的。
    cout << f[(n+2)&1][0][0];
    return 0;
}

Ideas:
Es muy similar a las dos preguntas "Pequeño rey" y "Campo de maíz". Se recomienda enfáticamente entender esas dos preguntas primero.

Todavía es el método clásico de dp de estilo y:
1. Representación de estado
f[i][j][k] : la artillería
delantera ise ha establecido (incluida la primera ifila), y iel estado de la primera fila es jy todos i-1los planes de la primera fila son . El atributo es Max (la artillería con la mayor ubicación), (el estado es / se refiere al binario para indicar la ubicación de la artillería, un medio común de suprimir dp),k

jk

2. Cálculo del estado
Después del bautismo de la presión estatal anterior dp, analicemos primero el "estado" y la "transición" por separado:
1. ¿Bajo qué circunstancias ies legal un estado (línea)?
1. La artillería en una sola fila no puede atacarse entre sí (como máximo puede existir una artillería dentro de tres bloques).
En segundo lugar, la artillería no se puede colocar en las montañas.

2. ¿Bajo qué circunstancias es legal transferir el estado a al estado b (línea iy línea)? Uno, a y b no pueden tener artillería en la misma columna al mismo tiempo.i-1

Finalmente, si se cumplen las condiciones anteriores, el estado puede ser transferido
f[i][a][b] = max(f[i][a][b], f[i-1][b][c] + cnt[a])
Desde el punto de vista práctico:
1. f[i][a][b] = Se ha colocado la primera fila i, y el estado de la fila i es a, y el estado de la fila i-1 es b,
2. f[i-1][b][c] = se ha colocado la primera fila i-1, y el estado de la fila i-1 es b, y el estado de la fila i-2 es c, luego use 2 para
actualizar 1, debe agregar la cantidad de artillería colocada en el estado actual a.

Si es útil, por favor dale a Me gusta gratis ~ ¡Alguien mirando es la motivación para ayudarme a escribir!

Descargo de responsabilidad:
la fuente de la idea del algoritmo es el Sr. Y. Para obtener más detalles, consulte https://www.acwing.com/
Este artículo solo se usa para registros de aprendizaje e intercambios

Supongo que te gusta

Origin blog.csdn.net/SRestia/article/details/130208667
Recomendado
Clasificación