这两道题如出一辙,只是判断有效状态有一点小差异。
每一行的状态只与前面两行的状态有关,每行可以压缩为二进制的集合,设状态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,即两种状态交替进行。
对于每一行可能出现的组合,可以先预处理出每一种有效状态。
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 }
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 }