POJ3254 Corn Fields(状压DP)

题目给个n×m的地图,1可以放玉米0不可以,现在要放玉米,玉米上下左右不能相邻,问放法有几种。

当前一行的决策只会影响下一行,所以状压DP之:

  • dp[i][S]表示前i行放完且第i行放玉米的列的集合是S的方案数

先预处理出每一行合法的放法的集合,合法的放法其实是很少的,通过枚举合法的集合来转移。

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 bool map[12][12];
 5 int n,m,d[12][1<<12],sta[12][1<<12],sn[12];
 6 bool isok(int x,int s){
 7     for(int i=0; i<m; ++i){
 8         if(i && ((s>>i)&1) && ((s>>i-1)&1)) return 0;
 9         if(((s>>i)&1) && !map[x][i]) return 0;
10     }
11     return 1;
12 }
13 int main(){
14     scanf("%d%d",&n,&m);
15     for(int i=0; i<n; ++i){
16         for(int j=0; j<m; ++j) scanf("%d",&map[i][j]);
17     }
18     for(int i=0; i<n; ++i){
19         for(int j=0; j<(1<<m); ++j){
20             if(isok(i,j)) sta[i][sn[i]++]=j;
21         }
22     }
23     for(int i=0; i<sn[0]; ++i) d[0][sta[0][i]]=1;
24     for(int i=1; i<n; ++i){
25         for(int j=0; j<sn[i]; ++j){
26             for(int k=0; k<sn[i-1]; ++k){
27                 if(sta[i][j]&sta[i-1][k]) continue;
28                 d[i][sta[i][j]]+=d[i-1][sta[i-1][k]];
29                 d[i][sta[i][j]]%=100000000;
30             }
31         }
32     }
33     int res=0;
34     for(int i=0; i<sn[n-1]; ++i){
35         res+=d[n-1][sta[n-1][i]];
36         res%=100000000;
37     }
38     printf("%d",res);
39     return 0;
40 }

 

你可能感兴趣的:(POJ3254 Corn Fields(状压DP))