洛谷 P1879 玉米田(状压DP入门题)

传送门

https://www.cnblogs.com/violet-acmer/p/9852294.html

 

题解:

  相关变量解释:

1 int M,N;
2 int plant[maxn][maxn];//草场情况
3 struct Node
4 {
5     int status;//状态
6     int res;//方案
7     Node(int a=0,int b=0):status(a),res(b){}
8 };
9 vector<Node >dp[maxn];//dp[i][j] : 第i行的j状态能达到的最大方案

  根据dp定义,很容易写出状态转移方程:

 1 for(int i=1;i <= M;++i)
 2 {
 3     for(int j=0;j <= maxNum;++j)
 4     {
 5         int res=Find(j,i-1);//查找与上一次决策没有相邻的草地的决策个数
 6         //isSat1() : 判断草地是否合法,即判断不含有相邻草场
 7         //isSat2() : 判断当前决策是否有相邻的草地
 8         if(isSat1(i,j) && isSat2(j) && res)
 9             dp[i].pb(Node(j,res));
10     }
11 }

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<vector>
 4 using namespace std;
 5 #define R(x) (1<<x)
 6 #define pb(x) push_back(x)
 7 const int MOD=1e8;
 8 const int maxn=12+10;
 9 
10 int M,N;
11 int plant[maxn][maxn];//草场情况
12 struct Node
13 {
14     int status;//状态
15     int res;//方案
16     Node(int a=0,int b=0):status(a),res(b){}
17 };
18 vector<Node >dp[maxn];//dp[i][j] : 第i行的j状态能达到的最大方案
19 bool isSat1(int i,int x)//判断草地是否合法
20 {
21     int index=N;
22     for(int j=1;j <= N;++j)
23         if(plant[i][index--] == 0 && (R(j-1)&x) != 0)
24             return false;
25     return true;
26 }
27 bool isSat2(int x)//判断当前决策是否有相邻的草地
28 {
29     for(int j=2;;++j)
30     {
31         int val=R(j-1)+R(j-2);
32         if(val > x)
33             return true ;
34         if((val&x) == val)
35             return false;
36     }
37     return true;
38 }
39 int Find(int now,int i)//查找与上一次决策没有相邻的草地的决策个数
40 {
41     int res=0;
42     for(int j=0;j < dp[i].size();++j)
43     {
44         Node node=dp[i][j];
45         int pre=node.status;
46         if((pre&now) == 0)
47             res=res%MOD+node.res;
48     }
49     return res%MOD;
50 }
51 void Solve()
52 {
53     int maxNum=(1<<N)-1;
54     dp[0].pb(Node(0,1));
55     for(int i=1;i <= M;++i)
56     {
57         for(int j=0;j <= maxNum;++j)
58         {
59             int res=Find(j,i-1);
60             if(isSat1(i,j) && isSat2(j) && res)
61                 dp[i].pb(Node(j,res));
62         }
63     }
64     int res=0;
65     for(int i=0;i < dp[M].size();++i)
66         res=res%MOD+dp[M][i].res;
67     printf("%d\n",res%MOD);
68 }
69 int main()
70 {
71     scanf("%d%d",&M,&N);
72     for(int i=1;i <= M;++i)
73         for(int j=1;j <= N;++j)
74             scanf("%d",plant[i]+j);
75     Solve();
76 }
View Code

 

posted @ 2018-11-21 21:42  HHHyacinth  阅读(330)  评论(0编辑  收藏  举报