P1879 [USACO06NOV]玉米田Corn Fields[轮廓线DP]
状压暴力显然可做。但是数据出的再大一点就要稳T了。理论$O(n4^m)$,只不过实际跑不满。
考虑用轮廓线DP,设$f(i,j,S)$为处理到$(i,j)$时候(这格还不确定)的轮廓线为$S$的情况(相当于把$(i,1\sim j-1)$和$(i-1,j\sim m)$的$m$个数用$S$压起来)下有多少种合法方案,然后考虑$(i,j)$这个格子填什么。
不管怎么样,这格都可以填0,将这个推向$f(i,j+1,S')$。如果左一格或上一格填了1或者这格有障碍,那不能填1,否则可以填1,同理推向$f(i,j+1,S'')$。
这里的$S'和S''$是位运算将第$j$位进行$0/1$变换的。
注意考虑细节:一行的轮廓线推完($j$循环到$m$结束后)的这个状态是要作为下一行的起始状态的。也就是$f(i,m,S)$应当推向$f(i+1,1,S')$。
我们可以通过直接滚动数组来一格一格往下推,避免换行之类的操作,详见code。
其次,这样DP不需要考虑相邻合不合法,因为我在填的时候推向后面的状态这个操作已经是保证他合法的了,即使是枚举出了不合法的,他的方案数也会是$0$,也没办法有累加作用。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define dbg(x) cerr << #x << " = " << x <<endl 7 using namespace std; 8 typedef long long ll; 9 typedef double db; 10 typedef pair<int,int> pii; 11 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 12 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;} 14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;} 15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;} 16 template<typename T>inline T read(T&x){ 17 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 18 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 19 } 20 const int P=1e8; 21 int mp[14][14],f[2][1<<12]; 22 int m,n,now,tmp,ans; 23 24 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout); 25 read(n),read(m); 26 for(register int i=1;i<=n;++i)for(register int j=1;j<=m;++j)read(mp[i][j]); 27 f[0][0]=1; 28 for(register int i=1;i<=n;++i){ 29 for(register int j=1;j<=m;now^=1,++j){ 30 for(register int k=0;k<1<<m;++k)if(f[now][k]){ 31 int p2=k&(1<<j-1),p1=j==1?0:k&(1<<j-2); 32 tmp=p2?k^(1<<j-1):k,f[now^1][tmp]+=f[now][k],f[now^1][tmp]>=P&&(f[now^1][tmp]-=P); 33 if(mp[i][j]&&!p1&&!p2) 34 tmp=k|(1<<j-1),f[now^1][tmp]+=f[now][k],f[now^1][tmp]>=P&&(f[now^1][tmp]-=P); 35 f[now][k]=0; 36 } 37 } 38 } 39 for(register int k=0;k<1<<m;++k)ans+=f[now][k],ans>=P&&(ans-=P); 40 return printf("%d\n",ans),0; 41 }
理论$O(nm2^m)$。