poj 3254 状压dp

题意:给出一个n行m列的草地,1表示肥沃,0表示贫瘠,现在要把一些牛放在肥沃的草地上,但是要求所有牛不能相邻,问你有多少种放法。

链接:点我

定义状态dp【i】【j】,第 i 行状态为 j 的时候放牛的种数。

去年暑假做过的题,现在忘光了

 1 #include <cstdio>
 2 #include <cstring>
 3 const int N = 13;
 4 const int M = 1<<N;
 5 const int mod = 100000000;
 6 int st[M],map[M];  //分别存每一行的状态和给出地的状态
 7 int dp[N][M];  //表示在第i行状态为j时候可以放牛的种数
 8 bool judge1(int x)  //判断二进制有没有相邻的1
 9 {
10     return (x&(x<<1));
11 }
12 bool judge2(int i,int x)
13 {
14     return (map[i]&st[x]);
15 }
16 int main()
17 {
18     int n,m,x;
19     while(~scanf("%d%d",&n,&m))
20     {
21         memset(st,0,sizeof(st));
22         memset(map,0,sizeof(map));
23         memset(dp,0,sizeof(dp));
24         for(int i=1;i<=n;i++)
25         {
26             for(int j=1;j<=m;j++){
27                 scanf("%d",&x);
28                 if(x==0)
29                     map[i]+=(1<<(j-1));
30             }
31 
32         }
33         int k=0;
34         for(int i=0;i<(1<<m);i++){
35             if(!judge1(i))
36                 st[k++]=i;
37         }
38         for(int i=0;i<k;i++)
39         {
40             if(!judge2(1,i))
41                 dp[1][i]=1;
42         }
43         for(int i=2;i<=n;i++)
44         {
45             for(int j=0;j<k;j++)
46             {
47                 if(judge2(i,j))  //判断第i行 假如按状态j放牛的话行不行。
48                     continue;
49                 for(int f=0;f<k;f++)    //上一行的状态
50                 {
51                     if(judge2(i-1,f))   //剪枝 判断上一行与其状态是否满足
52                         continue;
53                     if(!(st[j]&st[f]))
54                         dp[i][j]+=dp[i-1][f];
55                 }
56             }
57         }
58         int ans=0;
59         for(int i=0;i<k;i++){
60             ans+=dp[n][i];
61             ans%=mod;
62         }
63         printf("%d\n",ans);
64     }
65     return 0;
66 }

 

posted @ 2015-05-14 08:48  miao_a_miao  阅读(143)  评论(0编辑  收藏  举报