Corn Fields(poj

 题目链接:http://poj.org/problem?id=3254

  

 题意:

  一个n*m的矩形,告诉你哪些格子可以放棋子,哪些格子不能放(1表示能放,0表示不能放)。且相邻格子不能放。问一共有多少种放棋子的方案。(一个棋子也不放算一种方案,答案对1e8取模)。

 题解:

  状态压缩递推。

  设dpi,s表示第i行,方案为s(s为一个用来记录方案的二进制数,被选列为1,不被选列为0)。则dpi,s = sum{dpi-1,ss||s&ss==0} [s合法] || 0 [s不合法](s合法的判断标准为是否选了左右相邻格子,s&ss==0判断的是是否选了上下相邻格子) 。

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define LL long long
 5 #define RI register int
 6 #define KI 100000000
 7 using namespace std;
 8 const int INF = 0x7ffffff ;
 9 const int N = 12 + 2 ;
10 
11 inline int read() {
12     int k = 0 , f = 1 ; char c = getchar() ;
13     for( ; !isdigit(c) ; c = getchar())
14       if(c == '-') f = -1 ;
15     for( ; isdigit(c) ; c = getchar())
16       k = k*10 + c-'0' ;
17     return k*f ;
18 }
19 int n, m ;
20 bool v[N][N] ; int dp[N][1<<N] ;
21 
22 int main() {
23     n = read(), m = read() ;
24     for(int i=1;i<=n;i++) 
25      for(int j=1;j<=m;j++) 
26       v[i][j] = read() ;
27     dp[1][0] = 1 ;
28     for(int s=1;s<(1<<m);s++) {
29         bool flag = 0 ;
30         for(int j=1;j<=m;j++) {        
31             if(!v[1][j] && s&(1<<(j-1))) {
32                 flag = 1; break ;
33             }
34         }
35         for(int j=1;j<m;j++) if(s&(1<<(j-1)) && s&(1<<j)) { flag = 1 ; break ; }
36         if(!flag) dp[1][s] = 1 ;
37     }
38     for(int i=2;i<=n;i++) {
39         for(int s=0;s<(1<<m);s++) {
40             dp[i][s] = 0 ; bool flag = 0 ;
41             for(int j=1;j<=m;j++) 
42                 if(!v[i][j] && s&(1<<(j-1))) { // 该状态中有不能放的格子 
43                     flag = 1 ; break ;
44                 } 
45             for(int j=1;j<m;j++) if(s&(1<<(j-1)) && s&(1<<j)) {
46                 flag = 1 ; break ;
47             }
48             if(flag) continue ;
49             for(int ss=0;ss<(1<<m);ss++)  { // 枚举上一行状态
50                 if(ss&s) continue ; // 上下格相邻
51                 dp[i][s] += dp[i-1][ss] ; dp[i][s] %= KI ;
52             }
53         }
54     }
55     int ans = 0 ;
56 //    for(int s=0;s<(1<<m);s++) printf("%d %d\n",s,dp[1][s]) ; 
57     for(int s=0;s<(1<<m);s++) ans = (ans+dp[n][s])%KI ;
58     printf("%d",ans) ;
59     return 0 ;
60 }

 

posted @ 2018-03-23 16:31  zubizakeli  阅读(121)  评论(0编辑  收藏  举报