P1879 [USACO06NOV]玉米田Corn Fields(状压dp)
P1879 [USACO06NOV]玉米田Corn Fields
状压dp水题
看到$n,m<=12$,肯定是状压鸭
先筛去所有不合法状态,蓝后用可行的状态跑一次dp就ok了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define re register 5 using namespace std; 6 const int p=1e9; 7 int n,m,a[13],f[13][4098]; 8 int t[13][4098],len[13]; 9 int mod(int a){return a<p?a:a-p;} 10 void prepare(){ 11 for(re int i=1;i<=n;++i) 12 for(re int j=0;j<(1<<m);++j){ 13 if((j&(j<<1))||(j&(j>>1))||(j&a[i])) continue; 14 t[i][++len[i]]=j;//合法的存起来 15 } 16 } 17 int main(){ 18 scanf("%d%d",&n,&m); int q; 19 for(re int i=1;i<=n;++i) 20 for(re int j=0;j<m;++j) 21 scanf("%d",&q),a[i]=(a[i]<<1)+(q^1);//转存二进制并取反(有利于后面的筛) 22 prepare(); 23 for(re int i=1;i<=len[1];++i) f[1][t[1][i]]=1; 24 for(re int i=2;i<=n;++i) 25 for(re int j=1;j<=len[i-1];++j) 26 for(re int k=1;k<=len[i];++k){ 27 if(t[i-1][j]&t[i][k]) continue;//不合法 28 f[i][t[i][k]]=mod(f[i][t[i][k]]+f[i-1][t[i-1][j]]); 29 } 30 int ans=0; 31 for(re int i=1;i<=len[n];++i) ans=mod(ans+f[n][t[n][i]]); 32 printf("%d",ans); 33 return 0; 34 }