poj 3254

n乘m的矩阵,1表示这块区域可以放牛,0,表示不能,而且不能在相邻的(包括上下相邻)两个区域放牛,问有多少种放牛的方法,全部不放也是一种方法。

对于每块可以放牛的区域,有放或者不放两种选择,状压DP,dp[i][j]表示第 i 行以state[j]这种状态的时候和方法取值。

具体的参考http://www.tuicool.com/articles/JVzMVj

写的很详细。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 int dp[20][600],cas=0,n,m;
 8 int state[600],cur[20];
 9 int mod=1e9;
10 
11 void init()
12 {
13     int q=(1<<m);
14     for (int i=0 ; i<q ; i++)
15     {
16         if (i&(i<<1)) continue;
17         state[++cas]=i;
18     }
19 }
20 
21 bool judge(int x,int y)
22 {
23     if (x&cur[y]) return false;//不符合
24     return true;
25 }
26 
27 int main()
28 {
29     scanf("%d%d",&n,&m);
30     init();
31     for (int i=1 ; i<=n ; i++){
32         cur[i]=0;int x;
33         for (int j=1 ; j<=m ; j++){
34             scanf("%d",&x);
35             if (x==0) cur[i]+=(1<<(m-j));
36         }
37     }
38     for (int i=1 ; i<=cas ; i++)
39         if (judge(state[i],1))
40             dp[1][i]=1;
41     for (int i=2 ; i<=n ; i++){
42         for (int j=1 ; j<=cas ; j++){
43             if (judge(state[j],i)==false) continue;
44             for (int k=1 ; k<=cas ; k++){
45                 if (judge(state[k],i-1)==false) continue;
46                 if (state[k]&state[j]) continue;
47                 dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;
48             }
49         }
50     }
51     int maxn=0;
52     for (int i=1 ; i<=cas ; i++)
53         maxn=(maxn+dp[n][i])%mod;
54     printf("%d\n",maxn);
55     return 0;
56 }
View Code

 

posted on 2016-07-14 11:58  蜘蛛侦探  阅读(349)  评论(0编辑  收藏  举报