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

 

posted @ 2018-10-19 19:38  kafuuchino  阅读(144)  评论(0编辑  收藏  举报