#P1879 [USACO06NOV]Corn Fields G 状压dp

P1879 [USACO06NOV]Corn Fields G 状压dp

https://www.luogu.com.cn/problem/P1879

思路:

开dp[13][20000]表示第i行,数k在二进制下在该行的某种决策,bit为1为种,否则不种


#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 105
#define minn -105
#define ll long long int
#define ull unsigned long long int
#define mod 100000000
inline int read()
{
    int ans=0;
    char last=' ',ch=getchar();
    while(ch<'0'|ch>'9')last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans;
    return ans;
}
int n,m;
int dp[13][20000];
int save[13];
int main()
{
    int n,m;
    cin>>n>>m;
    int ed=(1<<m);
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        int cur=0,tmp;
        for(int j=0;j<m;j++)
        {
            cin>>tmp;
            cur<<=1;
            cur+=tmp;
        }
        save[i]=cur; //记录当前行可选状态
    }

    dp[0][0]=1;
    save[0]=INF;

    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=save[i];j++)
        {
            if(save[i]==(save[i]|j)) //更新决策序列dp
            {
                bool ok=1;
                int tmp=3;
                while(tmp<=j)
                {
                    if((tmp&j)==tmp) //检查当前决策j是否出现了两个连续的1
                    {
                        ok=0;
                        break;
                    }
                    tmp<<=1;
                }
                if(ok)
                {
                    int minx=min(save[i-1],(ed-1)^j);
                    for(int k=0;k<=minx;k++)
                    {
                        if((k&j)==0)dp[i][j]+=dp[i-1][k];
                    }
                    //cout<<i<<" "<<j<<" "<<dp[i][j]<<endl;
                }
            }
            if(i==n)
            {
                ans+=dp[i][j];
                ans%=mod;
            }

        }
    }
    cout<<ans<<endl;

    return 0;
}

posted @ 2020-07-02 10:13  et3_tsy  阅读(114)  评论(0编辑  收藏  举报