poj3254--Corn Fields--状压dp
Posted BK-Edwina
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj3254--Corn Fields--状压dp相关的知识,希望对你有一定的参考价值。
Description
现在有一片N*M的田地,其中有一些格子不能种玉米,且种植玉米时,也不能同时种在相邻的两个格子。求种植方案数。
Sample Input
2 3
1 1 1
0 1 0
Sample Output
9
题解:
状压dp的基础题啊qwq但我还是写了有一会儿……(完全忘了这种题的套路了)
这道题加入了一点搜索的思想,因为你有两个限制(本来就不能种+旁边已经种了所以不能种),用它们去进行剪枝来排除不符合题意的方案。
剩下的都在注释里了~
1 #include<iostream> 2 #include<cmath> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 const int N=13; 7 const int maxn=1<<N; 8 const int mod=1e8; 9 int state[maxn],map[maxn];//state----每一行的状态;map----存放地图初始状态 10 int f[N][maxn]; 11 bool judge_xianglin(int x)//判断一个数中,相邻两位是否同为1 12 { 13 return (x&(x<<1)); 14 //if 1----yes 15 //if 0----no 16 } 17 bool judge_same(int x,int y)//判断第x行按y的状态放是否可以 18 { 19 return (map[x]&state[y]); 20 //if 1----both 1 21 //if 0----no 22 } 23 int main() 24 { 25 int n,m,x; 26 while(~scanf("%d%d",&n,&m)) 27 { 28 for(int i=1;i<=maxn;i++) 29 { 30 state[i]=0; 31 map[i]=0; 32 //听说小数组初始化,用for比memset优 33 } 34 memset(f,0,sizeof(f)); 35 for(int i=1;i<=n;i++) 36 { 37 for(int j=1;j<=m;j++) 38 { 39 scanf("%d",&x); 40 if(x==0)//如果土地不良,这一行的第j个数变成1 41 map[i]=map[i]|(1<<(j-1)); 42 } 43 } 44 int k=0; 45 for(int i=0;i<(1<<m);i++) 46 { 47 if(!judge_xianglin(i)) 48 state[k++]=i;//这一步存的是左右不冲突的状态 49 } 50 for(int i=0;i<k;i++) 51 { 52 if(!judge_same(1,i)) 53 f[1][i]=1; 54 } 55 for(int i=2;i<=n;i++) 56 { 57 for(int j=0;j<k;j++) 58 { 59 if(judge_same(i,j))//判断state(j)是否适用于第i行 60 continue; 61 for(int t=0;t<k;t++) 62 { 63 if(judge_same(i-1,t)) 64 continue;//排除对于种植相邻的情况 65 if(!(state[j]&state[t]))//已经筛完了 66 f[i][j]+=f[i-1][t]; 67 } 68 } 69 } 70 int ans=0; 71 for(int i=0;i<k;i++) 72 { 73 ans+=f[n][i]; 74 ans%=mod; 75 } 76 printf("%d\n",ans); 77 } 78 return 0; 79 }
以上是关于poj3254--Corn Fields--状压dp的主要内容,如果未能解决你的问题,请参考以下文章