【题解】Luogu [USACO NOV] 玉米田 Corn Fields 状压dp

位运算一定要加括号!!!

我因为这个调了40分钟

嗯?01网格图,再看看数据范围,$n,m≤12$,嗯,状压没跑了

$F[i]$表示第$i$行的状态

$f[i][j]$表示前$i$行状态为$j$的合法方案数

$g[i]$表示状态是否合法

左右都是0的状态才合法,当且仅当$i<<1$和$i>>1$都为0的时候合法

当$j==j&F[i]$时,即在肥沃的土地上可以种草时满足题意

且当$j&k==0$时,即上一行与这一行的这个格子没有公共边时,满足题意

code

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 namespace gengyf{
 4 #define ll long long
 5 //const int maxn=5e4+10;
 6 const int mod=1e9;
 7 inline int read(){
 8     int f=1,x=0;char s=getchar();
 9     while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
10     while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
11     return f*x;
12 }
13 int n,m,a[15][15],f[15][(1<<15)+10];
14 int F[15],g[(1<<15)+10],ans;
15 int main(){
16     m=read();n=read();
17     for(int i=1;i<=m;i++)
18         for(int j=1;j<=n;j++){
19             a[i][j]=read();
20             F[i]=(F[i]<<1)+a[i][j];
21         }
22     for(int i=0;i<(1<<n);i++){
23         g[i]=(!(i&(i<<1))&&(!(i&(i>>1))));
24     }
25     f[0][0]=1;
26     for(int i=1;i<=m;i++)
27         for(int j=0;j<(1<<n);j++){
28             if(g[j]&&(F[i]&j)==j){
29                 for(int k=0;k<(1<<n);k++){
30                     if((k&j)==0){
31                         f[i][j]=(f[i][j]+f[i-1][k])%mod;
32 //                        cout<<f[i][j]<<" ";
33                     }
34                 }
35             }
36         }
37     for(int i=0;i<(1<<n);i++){
38         ans+=f[m][i];ans%=mod;
39 //        cout<<f[m][i]<<" ";
40     }
41     printf("%d",ans);
42     return 0;
43 }
44 }
45 signed main(){
46   gengyf::main();
47   return 0;
48 }
View Code
原文地址:https://www.cnblogs.com/gengyf/p/11673587.html