POJ-3254 Corn Fields 状态压缩DP+滚动数组
题目链接:http://poj.org/problem?id=3254
状态压缩,用01分别表示pasture不能plant和能plant。转移方程:f[k][i]=sum{f[k-1][j] | j是能满足i的状体,不产生冲突},显然可以用滚动数组优化。
详细的转移方法(上一个的状态设为k,i为所在行数):
1,如果前一个pasture已被plant,那么下一个pasture必定不能plant,所以f[i][k&~(1<<j)]+=f[i-1][k];
2,如果前一个pasture没有plant:
a,下一个pasture不plant,那么f[i][k]+=f[i-1][k];
b,如果下一个pasture的左边那个没有plant,即(k&(1<<(j-1)==0,那么这个pasture可以plant,则 f[p][k|(1<<j)]+=+f[!p][k]);
1 //STATUS:C++_AC_0MS_192KB 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<math.h> 6 #include<iostream> 7 #include<string> 8 #include<algorithm> 9 #include<vector> 10 #include<queue> 11 #include<stack> 12 using namespace std; 13 #define LL __int64 14 #define pdi pair<int,int> 15 #define Max(a,b) ((a)>(b)?(a):(b)) 16 #define Min(a,b) ((a)<(b)?(a):(b)) 17 #define mem(a,b) memset(a,b,sizeof(a)) 18 #define lson l,mid,rt<<1 19 #define rson mid+1,r,rt<<1|1 20 const int N=12,INF=0x3f3f3f3f,MOD=100000000; 21 const double DNF=100000000000; 22 23 int map[N][N],f[2][(1<<N)+10]; 24 int n,m; 25 26 int main() 27 { 28 // freopen("in.txt","r",stdin); 29 int i,j,k,p,ans; 30 while(~scanf("%d%d",&n,&m)) 31 { 32 ans=0; 33 mem(f,0);f[0][0]=p=1; 34 for(i=0;i<n;i++) 35 for(j=0;j<m;j++) 36 scanf("%d",&map[i][j]); 37 for(i=0;i<n;i++){ 38 for(j=0;j<m;j++,mem(f[p=!p],0)){ 39 for(k=0;k<(1<<m);k++){ 40 if(k&(1<<j)) 41 f[p][k&~(1<<j)]=(f[p][k&~(1<<j)]+f[!p][k])%MOD; 42 else { 43 f[p][k]=(f[p][k]+f[!p][k])%MOD; 44 if((j && !(k&(1<<(j-1))) || !j ) && map[i][j]) 45 f[p][k|(1<<j)]=(f[p][k|(1<<j)]+f[!p][k])%MOD; 46 } 47 } 48 } 49 } 50 p=!p; 51 for(i=0;i<(1<<m);i++) 52 ans=(ans+f[p][i])%MOD; 53 54 printf("%d\n",ans); 55 } 56 return 0; 57 }