poj3254(bzoj1725)--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
",ans);
77     }
78     return 0;
79 }
View Code
原文地址:https://www.cnblogs.com/Beckinsale/p/7466846.html