Campos de maíz [estado compresión dp]

题目: El granjero John ha comprado una nueva pastura rectangular exuberante compuesta de M por N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) parcelas cuadradas. Quiere cultivar maíz delicioso para las vacas en varios cuadrados. Lamentablemente, algunos de los cuadrados son infértiles y no se pueden plantar. Canny FJ sabe que a las vacas no les gusta comer cerca una de la otra, por lo que al elegir qué cuadrados plantar, evita elegir cuadrados adyacentes; no hay dos cuadrados elegidos que compartan una ventaja. Todavía no ha tomado la decisión final sobre qué cuadrados plantar.
Al ser un hombre de mente muy abierta, el granjero John quiere considerar todas las opciones posibles sobre cómo elegir los cuadrados para plantar. ¡Tiene una mente tan abierta que considera no elegir cuadrados como una opción válida! Ayude al granjero John a determinar la cantidad de formas en que puede elegir los cuadrados para plantar.

Tema : Los agricultores tienen una pradera matriz para la cría de ganado. Se puede criar un bloque de 1. Un agricultor de 0 no se puede criar. Además, cada vaca no puede ser adyacente. Ahora te daré una pradera y te preguntaré cuántos esquemas de cultivo tiene tu nombre de granja.

entrada

2 3
1 1 1
0 1 0

salida

9

Análisis

Cada pedazo de tierra tiene solo dos estados: pasto y no pasto. Cada pasto tiene dos estados de pastoreo y no pastoreo. Puede ser representado por 0 1 y comprimido en este estado.

Existen dos restricciones :

  1. Solo puede pastar ganado en pastos
  2. Los pastos adyacentes no pueden pastar simultáneamente

Ahora veamos cómo lidiar con estas dos situaciones con operaciones de bit

1. Si 1 significa pasto, 0 significa que no

Línea i: 0 0 1 0 1 0 1

Situación de pastoreo: 1 0 0 1 0 0 1

Bitwise y 1 0 0 0 0 0 0 0 ---> ≠ 0

Conclusión a> Si una vaca se coloca en un lugar que no es un pasto, el resultado de & no es 0

Línea i 1 0 1 1 0 0 1

Situación de pastoreo 1 0 1 1 0 0 1

Rebaño << 1 0 1 1 0 0 1 0

Bitwise y 0 0 1 0 0 0 0 ≠ 0

Conclusión b> Si el ganado se pone en el pasto adyacente, la situación de pastoreo del ganado << 1 y el pasto y el valor no es 0

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
const int mod = 1e8;
int n, m;
int mn[15], dp[15][1<<13], vis[15][1<<13];
//mn[i]存储第 i 行最大的牧场状态,dp[i][k]表示第i行的状态为k时,前i行的最大方案数。,vis[i][j]表示第 i 行的 j 状态是否合法 
int main(){
    scanf("%d%d", &n, &m);
    for(int i=0; i<n; i++){
        int ans = 0;
        for(int j=0; j<m; j++){
            int a; scanf("%d", &a);
            ans = (ans<<1) + a;//ans左移一位,空出的一位记录当前是否有牧场
        }
        mn[i] = ans;
        for(int j=0; j<=mn[i]; j++){//枚举第i行的状态j
            if((j & mn[i]) != j) continue;//在没有牧场的地方放了牛
            if(j & (j<<1)) continue;//在相邻的牧场放了牛
            vis[i][j] = 1;//第i行的j状态合法
        }
    }
    for(int i=0; i<n; i++){//枚举行
        for(int j=0; j<=mn[i]; j++){//枚举状态
            if(!vis[i][j]) continue;//不合法则跳过
            if(i == 0) dp[i][j] = 1;//第一行任何合法的方案都可以
            else{
                for(int k=0; k<=mn[i-1]; k++){//枚举上一行的状态
                    if(!vis[i-1][k]) continue;//不合法则跳过
                    if((j & k) != 0) continue;//在竖直方向上的相邻位置放了牛
                    dp[i][j] = (dp[i][j]%mod + dp[i-1][k]%mod)%mod;//当前总共的方案数
                }
            }
        }
    }
    int ans = 0;
    for(int i=0; i<=mn[n-1]; i++){//枚举第n行上一行的状态
        if(!vis[n-1][i]) continue;//不合法则跳过
        ans = (ans%mod +dp[n-1][i]%mod)%mod;//求最终的方案和
    }
    printf("%d\n", ans);
    return 0;
}

Supongo que te gusta

Origin www.cnblogs.com/hzoi-poozhai/p/12694182.html
Recomendado
Clasificación