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 }

 

你可能感兴趣的:(poj)