HDU 4539 郑厂长系列故事——排兵布阵 (状态压缩DP)

来源:互联网 发布:淘客app源码 编辑:程序博客网 时间:2024/05/28 05:14



中文题,题意不再累赘。


思路:对于第 i 行的放士兵,影响它的只有第 i-1 行和 i-2 行,所以暴力枚举符合这三行的状态


 state[i],state[j],state[k].  接下来就是二进制的巧妙应用了。


具体题解看代码注释!!!


#include<cstdio>#include<stdlib.h>#include<string.h>#include<string>#include<map>#include<cmath>#include<iostream>#include <queue>#include <stack>#include<algorithm>#include<set>using namespace std;#define INF 1e8#define inf -0x3f3f3f3f#define eps 1e-8#define LL long long#define N 100001#define mol 100000000int lp(int a,int b){return a&b;}int dp[105][200][200];//dp[i][j][k],表示第 i 行是 state[j]状态i-1行是state[k]状态的最大值int state[200];//符合规定的状态int base[200];//给定矩阵的初始状态int sum[200];//sum[i]:状态satet[i]的士兵数int n,m,g;int main(){while(~scanf("%d%d",&n,&m)){memset(base,0,sizeof(base));          memset(dp,0,sizeof(dp));          memset(state,0,sizeof(state));          memset(sum,0,sizeof(sum));  if(n==0||m==0){printf("0\n");continue;}for(int i=0;i<n;i++){for(int j=0;j<m;j++){scanf("%d",&g);if(g==0)base[i]+=1<<(j);//初始状态二进制表示}}int num=0;for(int i=0;i<(1<<m);i++){if(lp(i,i<<2)||lp(i,i>>2)) continue;//状态i要满足它不能攻击它的前两个和后两个int k=i;while(k)//算出k有多少个1(士兵){sum[num]+=k&1;k=k>>1;}state[num++]=i;}for(int i=0;i<num;i++)//初始第0行的状态{if(lp(state[i],base[0])) continue;dp[0][i][0]=sum[i];}for(int i=0;i<num;i++)//在满足第0行的状态下寻找第1行的状态{if(lp(state[i],base[1])) continue;for(int j=0;j<num;j++){if(lp(state[j],base[0])) continue;if(lp(state[j]<<1,state[i])||lp(state[j]>>1,state[i])) continue;dp[1][i][j]=max(dp[1][i][j],dp[0][j][0]+sum[i]);}}for(int i=0;i<num;i++)//在满足第0,1行的状态下寻找第2行的状态{if(lp(state[i],base[2])) continue;for(int j=0;j<num;j++){if(lp(state[j],base[1])) continue;for(int k=0;k<num;k++){if(lp(state[k],base[0])) continue;if(lp(state[i]<<1,state[j])||lp(state[i]>>1,state[j])) continue;if(lp(state[j]<<1,state[k])||lp(state[j]>>1,state[k])) continue;if(lp(state[i],state[k])) continue;dp[2][i][j]=max(dp[2][i][j],dp[1][j][k]+sum[i]);}}}for(int r=3;r<n;r++)//从第3行开始{for(int i=0;i<num;i++)//暴力枚举三行的状态state[i],state[j],state[k]{if(lp(base[r],state[i])) continue;for(int j=0;j<num;j++){if(lp(base[r-1],state[j])) continue;if(lp(state[i]<<1,state[j])||lp(state[i]>>1,state[j])) continue;for(int k=0;k<num;k++){if(lp(base[r-2],state[k])) continue;if(lp(state[j]<<1,state[k])||lp(state[j]>>1,state[k])) continue;if(lp(state[i],state[k])) continue;dp[r][i][j]=max(dp[r-1][j][k]+sum[i],dp[r][i][j]);}}}}int ans=0;for(int i=0;i<num;i++){for(int j=0;j<num;j++)ans=max(ans,dp[n-1][i][j]);}printf("%d\n",ans);}return 0;}/*6 61 0 0 0 0 10 0 0 0 0 00 0 1 1 0 00 0 1 1 0 00 0 1 1 0 01 0 1 1 0 13 31 1 11 1 11 1 16 60 0 0 0 0 00 0 0 0 0 00 0 1 1 0 00 0 0 0 0 00 0 0 0 0 00 0 0 0 0 06 61 1 1 1 1 11 1 1 1 1 11 1 1 1 1 11 1 1 1 1 11 1 1 1 1 11 1 1 1 1 10 61 61 1 1 1 1 12 61 1 1 1 1 11 1 1 1 1 1Answer:63212044*/


0 0
原创粉丝点击