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 }

 

你可能感兴趣的:(HDU)