hdu 2167 Pebbles(状态压缩DP)

入门级状态压缩dp题。

题意:从方格中取一些数,要求所取位置不相邻(包括对角线相邻),求最大的和。

做法:把每行的状态压缩成二进制数,设状态dp[i][p]为第i行取集合p,容易得出dp[i][p] = max{dp[i-1][q] + cnt[i][p]| 集合p,q可以共存},cnt[i][p]为第i行为集合p时所取得数的和。

View Code
  1 /*
  2  *Author:       Zhaofa Fang
  3  *Created time: 2013-03-31-10.33
  4  *Language:     C++
  5  */
  6 #include <cstdio>
  7 #include <cstdlib>
  8 #include <sstream>
  9 #include <iostream>
 10 #include <cmath>
 11 #include <cstring>
 12 #include <algorithm>
 13 #include <string>
 14 #include <utility>
 15 #include <vector>
 16 #include <queue>
 17 #include <stack>
 18 #include <map>
 19 #include <set>
 20 using namespace std;
 21 
 22 typedef long long ll;
 23 #define DEBUG(x) cout<< #x << ':' << x << endl
 24 #define REP(i,n) for(int i=0;i < (n);i++)
 25 #define REPD(i,n) for(int i=(n-1);i >= 0;i--)
 26 #define FOR(i,s,t) for(int i = (s);i <= (t);i++)
 27 #define FORD(i,s,t) for(int i = (s);i >= (t);i--)
 28 #define PII pair<int,int>
 29 #define PB push_back
 30 #define MP make_pair
 31 #define ft first
 32 #define sd second
 33 #define lowbit(x) (x&(-x))
 34 #define INF (1<<30)
 35 
 36 int k;
 37 int maz[17][17],dp[2][1600];
 38 int cnt[20][1600];
 39 int s[1600];
 40 bool ok(int x){
 41     if(x&(x<<1))return false;
 42     return true;
 43 }
 44 int fun(int x,int row,int n){
 45     int res=0,j=0;
 46     REP(j,n){
 47         if(x&(1<<j))res+=maz[row][j];
 48     }
 49     return res;
 50 }
 51 void pre_deal(int n){
 52 
 53     memset(s,0,sizeof(s));
 54     memset(cnt,0,sizeof(cnt));
 55     REP(i,(1<<n)){
 56         if(ok(i)){
 57             s[k++] = i;
 58         }
 59     }
 60     REP(i,n){
 61         REP(j,k)
 62         cnt[i][j] = fun(s[j],i,n);
 63     }
 64 }
 65 
 66 int main(){
 67     //freopen("in","r",stdin);
 68     //freopen("out","w",stdout);
 69     char str[100];
 70     while(gets(str)){
 71         int len = strlen(str);
 72         int n=0,res=0;
 73         REP(i,len){
 74             if(str[i]>='0'&&str[i]<='9')res = res*10+str[i]-'0';
 75             else {
 76                 maz[0][n++] = res;
 77                 res = 0;
 78             }
 79         }
 80         maz[0][n++]=res;
 81         FOR(i,1,n-1)REP(j,n)scanf("%d",&maz[i][j]);
 82         getchar();
 83         gets(str);
 84         k = 0;
 85         pre_deal(n);
 86         memset(dp,-1,sizeof(dp));
 87         int now = 1;
 88         REP(i,k)dp[now][i] = cnt[0][i];
 89         FOR(i,1,n-1){
 90             now ^= 1;
 91             REP(p,k){
 92                 REP(q,k){
 93                     if(s[p]&s[q])continue;
 94                     if(s[p]&(s[q]<<1))continue;
 95                     if(s[p]&(s[q]>>1))continue;
 96                     if(dp[now^1][q]==-1)continue;
 97                     dp[now][p] = max(dp[now][p],dp[now^1][q]+cnt[i][p]);
 98                 }
 99             }
100         }
101         int ans = 0;
102         REP(i,k)ans=max(ans,dp[now][i]);
103         printf("%d\n",ans);
104     }
105     return 0;
106 }

 

posted @ 2013-03-31 11:57  發_  阅读(595)  评论(0编辑  收藏  举报