1. 程式人生 > >P1879 [USACO06NOV]玉米田Corn Fields(狀壓dp)

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 }
View Code