[ An Ac a Day ^_^ ] POJ 3254 Corn Fields 状压dp

Posted 可是我不配

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ An Ac a Day ^_^ ] POJ 3254 Corn Fields 状压dp相关的知识,希望对你有一定的参考价值。

题意:

有一块n*m的土地

0代表不肥沃不可以放牛 1代表肥沃可以放牛

且相邻的草地不能同时放牛

问最多有多少种放牛的方法并对1e8取模

 

思路:

典型的状压dp 能状态压缩 能状态转移

能状态压缩的题的特点就是只有两种状态

所以用0 1表示两种状态 用位运算判断是否符合条件

然后将前一行的合理状态转移到后一行

最后统计最后一行的状态

dp[i][j]代表第i行以第j种状态放牛时有多少种不同的状态

 

(c++的语言特性是 封装 继承 多态~) 

 

 1 /* ***********************************************
 2 Author        :Sun Yuefeng
 3 Created Time  :2016/10/31 17:59:53
 4 File Name     :C.cpp
 5 ************************************************ */
 6 
 7 #include<cstdio>
 8 #include<iostream>
 9 #include<algorithm>
10 #include<cmath>
11 #include<cstring>
12 #include<string>
13 #include<bitset>
14 #include<map>
15 #include<set>
16 #include<stack>
17 #include<vector>
18 #include<queue>
19 #include<list>
20 #define M(a,b) memset(a,b,sizeof(a))
21 using namespace std;
22 typedef long long ll;
23 const int inf=0x3f3f3f3f;
24 const int maxn=1<<15;
25 const int mod=1e8;
26 int dx[8]= {0,0,1,-1,1,-1,1,-1};
27 int dy[8]= {1,-1,0,0,-1,1,1,-1};
28 
29 int _map[maxn]; //记录给出的每块地的状态
30 int st[maxn]; //记录每一行的状态
31 int dp[15][maxn];
32 
33 bool judge(int x) //判断相邻两位是否同时为1
34 {
35     return (x&(x<<1));
36 }
37 
38 bool judge(int x,int y) //判断两位是否同时为1
39 {
40     return _map[x]&st[y];
41 }
42 
43 int main()
44 {
45     //freopen("in.txt","r",stdin);
46     //freopen("out.txt","w",stdout);
47        int n,m;
48     while(cin>>n>>m){
49         int x;
50         M(dp,0),M(_map,0),M(st,0);
51         for(int i=0;i<n;i++)
52         {
53             for(int j=0;j<m;j++)
54             {
55                 cin>>x;
56                 if(!x)
57                 {
58                     _map[i]+=(1<<j); //向图中添加空地
59                 }
60             }
61         }
62         int k=0;
63         for(int i=0;i<(1<<m);i++) //初始化能不能以i状态放牛
64         {
65             if(!judge(i))
66             {
67                 st[k++]=i;
68             }
69         }
70         for(int i=0;i<k;i++) //初始化第一行状态
71         {
72             dp[0][i]=(!judge(0,i));
73         }
74         for(int i=1;i<n;i++)
75         {
76             for(int j=0;j<k;j++)
77             {
78                 if(judge(i,j)) continue; //判断第i行是否能以j的方式放牛
79                 for(int l=0;l<k;l++)
80                 {
81                     if(judge(i-1,l)) continue; //判断上一行状态
82                     if(!(st[j]&st[l])) //符合题意转移状态
83                         dp[i][j]+=dp[i-1][l];
84                 }
85             }
86         }
87         int ans=0;
88         for(int i=0;i<k;i++)
89         {
90             ans+=dp[n-1][i];
91             ans%=mod;
92         }
93         cout<<ans<<endl;
94     }    
95     return 0;
96 }

 

以上是关于[ An Ac a Day ^_^ ] POJ 3254 Corn Fields 状压dp的主要内容,如果未能解决你的问题,请参考以下文章

[ An Ac a Day ^_^ ][kuangbin带你飞]专题四 最短路练习 POJ 2240 Arbitrage spfa求负环

[ An Ac a Day ^_^ ] hdu 1003 dp

[ An Ac a Day ^_^ ] hdu 1662 数据结构 二叉树

[ An Ac a Day ^_^ ] hdu 2553 N皇后问题 搜索

[ An Ac a Day ^_^ ] HDU 1257 基础dp 最长上升子序列

[ An Ac a Day ^_^ ] hdu 5925 Coconuts 离散化+BFS求连通块