玉米田 状压dp

Posted 行码棋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了玉米田 状压dp相关的知识,希望对你有一定的参考价值。

和【国王】那题一样的套路

用一个数记录该行的状态,还要记录能够互相转移的状态

满足题意需要:

  • 不能出现连续的两个1
  • 两个数的与运算必须为0,这样才能转移

处理不育的玉米田,把不育的玉米田也转化为一个状态,将目标的状态和不育玉米田的状态做与运算,当结果大于0时,说明玉米放在了不育的玉米田上,需要舍弃这种情况。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 14,M = 1<<12,mod = 1e8;
int n,m;
vector<int>state;
vector<int>head[M];
int f[N][M],g[N];
//检查状态是否有连续的1
bool check(int x)
{
    for(int i=0;i<=m;i++)
        if((x>>i&1) && (x>>i+1)&1)
            return false;
    return true;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=0;j<m;j++)
        {
            int a;cin>>a;
            g[i] += !a << j;
        }
    
    for(int i=0;i< 1<<m;i++)
        if(check(i))
            state.push_back(i);
            
    for(int i=0;i<state.size();i++)
        for(int j=0;j<state.size();j++)
        {
            int a = state[i],b = state[j];
            if((a&b)==0)
                head[i].push_back(j);
        }
    
    f[0][0] = 1;
    for(int i=1;i<=n+1;i++)
        for(int j=0;j<state.size();j++)
        {
            if(g[i]&state[j]) continue;
            for(int b : head[j])
            {
                f[i][j] = (f[i][j] + f[i-1][b])%mod;
            }
        }
        
    cout<<f[n+1][0]<<'\\n';
    return 0;
}

以上是关于玉米田 状压dp的主要内容,如果未能解决你的问题,请参考以下文章

[USACO06NOV]玉米田Corn Fields (状压$dp$)

状压DP水题[USACO06NOV]玉米田Corn Fields

P1879 [USACO06NOV]玉米田Corn Fields 状压dp

[USACO06NOV]玉米田$Corn Fields$ (状压$DP$)

ybtoj 状压DP课堂过关 例题1jzoj 1266 luogu P1879 [USACO06NOV]Corn Fields G & 玉米田 & 种植方案

acwing 327. 玉米田