#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;
}