POJ 3254 Corn Fields:網格密鋪類 狀壓dp

Leohh發表於2017-08-16

題目連結:http://poj.org/problem?id=3254

題意:

  給你一片n*m的耕地,你可以在上面種玉米。但是其中有一些地方是荒蕪的,不能種植。並且種植玉米的地方不能相鄰。問你在這片地上有多少種種植方案。

 

題解:

  思路:一行一行種

  狀態表示:

    dp[state][i] = num of ways at ith row

    (1)當前種到了第i行

    (2)第i行有哪些地方種了玉米,狀態為state

  如何轉移:

    約束條件:

      (1)對於當前行,已經在某些地方種過了玉米,那麼在下一行的對應位置就不能再種。

      (2)在每一行內部,種植玉米不能相鄰。

      所以可以預處理(dfs)出在一行上每一種state對應的下一行可以種的方案nex。

    轉移條件:

      (1)state在當前第i行合法。

      (2)state對應的nex在i+1行合法。

      所以在讀入的時候,就可以預處理出每一行土地的情況field[i]。二進位制下每一位0代表可以種,1代表不能種。

      以上兩個條件就變成了:(state&field[i])==0 和 (nex&field[i+1])==0

    轉移:

      三重for迴圈,列舉種到第i行、當前行的種植方案state、state對應的下一行的種植方案nex。

      dp[state|nex][i+1] += dp[state][i]

 

AC Code:

 1 // optimizations:
 2 // 1) a state is legal at a row only if: state&field == 0
 3 // 2) preprocess the states can be transfered from another state
 4 
 5 #include <iostream>
 6 #include <stdio.h>
 7 #include <string.h>
 8 #include <vector>
 9 #define MAX_N 15
10 #define MAX_S (1<<14)
11 #define MOD 100000000
12 
13 using namespace std;
14 
15 int n,m;
16 int ans;
17 int field[MAX_N];
18 int dp[MAX_S][MAX_N];
19 vector<int> transfer[MAX_S];
20 
21 void read()
22 {
23     memset(field,0,sizeof(field));
24     cin>>n>>m;
25     int temp;
26     for(int i=0;i<n;i++)
27     {
28         for(int j=0;j<m;j++)
29         {
30             cin>>temp;
31             field[i]<<=1;
32             field[i]|=(!temp);
33         }
34     }
35     field[n]=(1<<m)-1;
36 }
37 
38 void dfs(int col,int state,int nex)
39 {
40     if(col>=m)
41     {
42         transfer[state].push_back(nex);
43         return;
44     }
45     if(!((state>>col)&1)) dfs(col+2,state,nex|(1<<col));
46     dfs(col+1,state,nex);
47 }
48 
49 void solve()
50 {
51     for(int state=0;state<(1<<m);state++)
52     {
53         dfs(0,state,0);
54     }
55     memset(dp,0,sizeof(dp));
56     for(int i=0;i<transfer[0].size();i++)
57     {
58         int state=transfer[0][i];
59         if(!(field[0]&state)) dp[state][0]=1;
60     }
61     for(int i=0;i<n;i++)
62     {
63         for(int state=0;state<(1<<m);state++)
64         {
65             if(dp[state][i]!=0 && !(field[i]&state))
66             {
67                 for(int j=0;j<transfer[state].size();j++)
68                 {
69                     int nex=transfer[state][j];
70                     if(!(field[i+1]&nex))
71                     {
72                         dp[nex][i+1]+=dp[state][i];
73                         dp[nex][i+1]%=MOD;
74                     }
75                 }
76             }
77         }
78     }
79 }
80 
81 void print()
82 {
83     cout<<dp[0][n]<<endl;
84 }
85 
86 int main()
87 {
88     read();
89     solve();
90     print();
91 }

 

相關文章