题解 P1879 【[USACO06NOV]玉米田Corn Fields】

顾z

2018-10-12 21:13:57

Solution

# [顾](https://www.luogu.org/blog/RPdreamer/#)[z](https://www.cnblogs.com/-guz/) ~~你没有发现两个字里的blog都不一样嘛~~ qwq 题目描述-->[p1879 [USACO06NOV]玉米田Corn Fields](https://www.luogu.org/problemnew/show/P1879) ### 分析 **下面的$n,m$为$n$行$m$列,与题目描述不符.** 难得做起了状压DP的题 $f[i]$代表第$i$行的状态.就是输入的状态,这个东西的话就直接算就好了. $$(f[i]<<=1)|=x$$ 初始化:$dp[0][0]=1$ 那么我们需要枚举每一行,再枚举状态$j$判断当前行的状态$f[i]$是否会包含状态$j$,即合法与否. 判断不能有相临的话,直接写一个函数即可 ![](https://i.loli.net/2018/10/12/5bc09deb93c6b.png) 这里就不多解释了. 然后在枚举上一行状态$k$是否与当前状态$j$不相邻.即上下&起来为0。 (这就涉及到了&的性质,两边为$True$才为$True$) $$ans=\sum_{i=0}^{(1<<m)-1}f[n][i]$$ 时间复杂度$O(n \times 2^{m+1})$ ``代码`` ```c++ #include<cstdio> #include<cctype> #define mod 100000000 #define R register using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int res[15][15],f[18],n,m,dp[18][1<<15],ans; inline bool ok(int state) { return ((state&(state>>1))==0 and (state&(state<<1))==0); } int main() { in(n),in(m); for(R int i=1;i<=n;i++) for(R int j=1,x;j<=m;j++) { in(x); (f[i]<<=1)|=x; } int state=(1<<m)-1; dp[0][0]=1; for(R int i=1;i<=n;i++) for(R int j=0;j<=state;j++) if(ok(j) and (f[i]&j)==j) for(R int k=0;k<=state;k++) if((k&j)==0) (dp[i][j]+=dp[i-1][k])%=mod; for(R int i=0;i<=state;i++) (ans+=dp[n][i])%=mod; printf("%d",ans%mod); } ```