Corn Fields

poj3254:http://poj.org/problem?id=3254

题意:给以n*m的方格,方格中有1或者0,在1的地方可以放置一个物品,但是在物品的上下左右不能有不物品,也可以不放,问你最够有多少种放法。

题解:很简单的状态dp。这里先统计数最多能放多少个,然后和棋盘放k的kind那题一样,最后的结果就是第n行各种状态以及放置0到最多的种类之和。其实,这一题,个数那一维是完全可以删除的,只要2维就可以了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 char mp[13][13];
 7 int dp[13][900][160];
 8 const int N=(1<<14);
 9 int n,m;
10 int total;
11 int s[N],ct[N],num;
12 int state[20];
13 bool isok(int x){
14    if(x&(x<<1))return false;
15    return true;
16 }
17 int counts(int x){
18     int ans=0;
19     while(x){
20         ans+=(x&1);
21         x/=2;
22     }
23    return ans;
24 }
25 void solve(){
26     num=0;
27    for(int i=0;i<(1<<m);i++){
28       if(isok(i)){
29         ++num;
30          s[num]=i;
31          ct[num]=counts(i);
32       }
33    }
34 }
35 void sum(){
36   total=0;
37   for(int i=1;i<=n;i++){
38     for(int j=1;j<=m;j++){
39         if(mp[i][j]=='1')
40             total++;
41     }
42   }
43 
44 }
45 void input(){
46     int cs=1,ans=0;
47    for(int i=1;i<=n;i++){
48         cs=1,ans=0;
49      for(int j=m;j>=1;j--){
50         if(mp[i][j]=='0'){
51             ans+=cs;
52         }
53         cs*=2;
54      }
55      state[i]=ans;
56    }
57 }
58 int main(){
59    while(~scanf("%d%d",&n,&m)){
60        memset(dp,0,sizeof(dp));
61        for(int i=1;i<=n;i++){
62         for(int j=1;j<=m;j++)
63             cin>>mp[i][j];
64        }
65        solve();
66        sum();
67        input();
68        for(int i=1;i<=num;i++){
69             if(state[1]&s[i])continue;
70          dp[1][i][0]=1;
71        }
72        for(int i=2;i<=n;i++){
73           for(int j=1;j<=num;j++){
74                 if(state[i]&s[j])continue;
75             for(int k=ct[j];k<=total;k++){
76                 for(int g=1;g<=num;g++){
77                     if(state[i-1]&s[g])continue;
78                     if(s[j]&s[g])continue;
79                     dp[i][j][0]+=dp[i-1][g][0];
80                     dp[i][j][0]%=100000000;
81                 }
82              }
83           }
84 
85        }
86       long long as=0;
87       for(int i=1;i<=num;i++){
88         for(int j=0;j<=total;j++){
89             as+=dp[n][i][0];
90              as%=100000000;
91        }
92       }
93       printf("%I64d
",as%100000000);
94    }
95 }
View Code
原文地址:https://www.cnblogs.com/chujian123/p/3874642.html