poj 1185 & hdu 4539(状态压缩DP)

这两道题如出一辙,只是判断有效状态有一点小差异。

每一行的状态只与前面两行的状态有关,每行可以压缩为二进制的集合,设状态dp[i][j][k]为第i行为集合j,第i-1行为集合k,

得出状态方程dp[i][j][k] = max{dp[i-1][k][r]+cnt[j]  | 状态i,j,k要能够共存}(cnt[j]为j在二进制下的1的个数,即士兵数)。第一维可以压缩为2,即两种状态交替进行。

对于每一行可能出现的组合,可以先预处理出每一种有效状态。

 

poj 1185
  1 /*
  2  *Author:       Zhaofa Fang
  3  *Created time: 2013-03-30-11.54
  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 maz[105],f[65],cnt[65];
 37 char str[105][15];
 38 int dp[2][65][65];
 39 int len;
 40 
 41 
 42 bool ok(int x){
 43     if(x&(x<<1))return false;
 44     if(x&(x<<2))return false;
 45     return true;
 46 }
 47 int count(int x){
 48     int res=0;
 49     while(x>0){
 50         res+=(x&1);
 51         x>>=1;
 52     }
 53     return res;
 54 }
 55 void fun(int m){
 56     REP(i,(1<<m)){
 57         if(ok(i)){
 58             f[len]=i;
 59             cnt[len++]=count(i);
 60         }
 61     }
 62 }
 63 int main(){
 64     //freopen("in","r",stdin);
 65     //freopen("out","w",stdout);
 66     int n,m;
 67     while(~scanf("%d%d",&n,&m)){
 68         memset(dp,-1,sizeof(dp));
 69         memset(f,0,sizeof(f));
 70         REP(i,n){
 71             scanf("%s",str[i]);
 72             maz[i]=0;
 73             REP(j,m){
 74                 if(str[i][j]=='H')maz[i]|=(1<<j);
 75             }
 76         }
 77         int now=1;
 78         len=0;
 79         fun(m);//枚举有效状态
 80         REP(i,len)if(!(f[i]&maz[0]))dp[now][i][0]=cnt[i];
 81         FOR(i,1,n-1){
 82             now^=1;
 83             REP(a,len){
 84                 if(maz[i]&f[a])continue;
 85                 REP(b,len){
 86                     if(f[a]&f[b])continue;
 87                     REP(c,len){
 88                         if((f[a]&f[c])||(f[b]&f[c]))continue;
 89                         if(dp[now^1][b][c]==-1)continue;
 90                         dp[now][a][b]=max(dp[now][a][b],dp[now^1][b][c]+cnt[a]);
 91                     }
 92                 }
 93             }
 94         }
 95         int ans=0;
 96         REP(i,len)REP(j,len)ans=max(ans,dp[now][i][j]);
 97         printf("%d\n",ans);
 98     }
 99     return 0;
100 }

 

hdu 4539
  1 /*
  2  *Author:       Zhaofa Fang
  3  *Created time: 2013-03-30-11.54
  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 maz[170],f[170],cnt[170];
 37 int dp[2][170][170];
 38 int len;
 39 
 40 
 41 bool ok(int x){
 42     if(x&(x<<2))return false;
 43     return true;
 44 }
 45 int count(int x){
 46     int res=0;
 47     while(x>0){
 48         res+=(x&1);
 49         x>>=1;
 50     }
 51     return res;
 52 }
 53 void fun(int m){
 54     REP(i,(1<<m)){
 55         if(ok(i)){
 56             f[len]=i;
 57             cnt[len++]=count(i);
 58         }
 59     }
 60 }
 61 int main(){
 62     //freopen("in","r",stdin);
 63     //freopen("out","w",stdout);
 64     int n,m;
 65     while(~scanf("%d%d",&n,&m)){
 66         memset(dp,-1,sizeof(dp));
 67         memset(f,0,sizeof(f));
 68         REP(i,n){
 69             maz[i]=0;
 70             REP(j,m){
 71                 int x;scanf("%d",&x);
 72                 if(!x)maz[i]|=(1<<j);
 73             }
 74         }
 75         int now=1;//用于压空间
 76         len=0;
 77         fun(m);//枚举有效状态
 78         REP(i,len)if(!(f[i]&maz[0]))dp[now][i][0]=cnt[i];
 79         FOR(i,1,n-1){
 80             now^=1;
 81             REP(a,len){
 82                 if(maz[i]&f[a])continue;
 83                 REP(b,len){
 84                     if(f[a]&(f[b]<<1))continue;
 85                     if(f[a]&(f[b]>>1))continue;
 86                     int tmp=0;
 87                     REP(c,len){
 88                         if(f[b]&(f[c]<<1))continue;
 89                         if(f[b]&(f[c]>>1))continue;
 90                         if(f[a]&f[c])continue;
 91                         if(dp[now^1][b][c]==-1)continue;
 92                         dp[now][a][b]=max(dp[now][a][b],dp[now^1][b][c]+cnt[a]);
 93                     }
 94                 }
 95             }
 96         }
 97         int ans=0;
 98         REP(i,len)REP(j,len)ans=max(ans,dp[now][i][j]);
 99         printf("%d\n",ans);
100     }
101     return 0;
102 }

 

posted @ 2013-03-30 23:13  發_  阅读(557)  评论(0编辑  收藏  举报