状态压缩(炮兵阵地)
作者:互联网
该题题意:在规定的地图里放大炮,大炮放的位置有限制,只有‘p’的位置能放;
并且在该点的四周两格内不能再放,找出能放大炮的最大数;
1 /*这道题跟前面做过的一道种植的题相似, 2 不过种植的那道题只会影响上下左右四个点, 3 这道题影响了8个点,所以要多一重l-2的判断; 4 */ 5 #include<cstdio> 6 #include<string.h> 7 #include<algorithm> 8 #include<iostream> 9 using namespace std; 10 const int maxn=70; 11 int dp[110][maxn][maxn]; 12 int mp[110]; 13 int a[maxn],sum[maxn]; 14 void init() 15 { 16 memset(sum,0,sizeof(sum)); 17 memset(a,0,sizeof(a)); 18 memset(dp,0,sizeof(dp)); 19 memset(mp,0,sizeof(mp)); 20 } 21 int cal(int x) //计算其中1的个数 22 { 23 int ret=0; 24 while(x) ret+=(x&1),x>>=1; 25 return ret; 26 } 27 int main() 28 { 29 int n,m; 30 while(scanf("%d%d",&n,&m)!=EOF){ 31 init(); 32 for(int i=1;i<=n;i++) 33 for(int j=1;j<=m;j++){ 34 char c; 35 cin>>c; 36 if(c=='H') mp[i]+=1<<(j-1); //标记地图; 37 //printf("%d ",mp[i]); 38 } 39 int num=0; 40 int cot=(1<<m)-1; 41 //找出满足该i点左右两个都没有不为‘1’的所有情况 42 for(int i=0;i<=cot;i++){ 43 if((!(i&(i<<1)))&&(!(i&(i<<2)))){ 44 a[num]=i; 45 sum[num++]=cal(i); //该情况下有多少个士兵 46 } 47 } 48 for(int i=0;i<num;i++) //初始化第一行的情况 49 if(!(mp[1]&a[i])) dp[1][i][0]=sum[i]; 50 for(int i=0;i<num;i++){ //初始化第二行的情况 51 if(a[i]&mp[2]) continue; //如果与地图不相符 52 for(int j=0;j<num;j++){ 53 if(a[j]&mp[1]) continue; 54 if(a[j]&a[i]) continue; //如果这两种情况有交集 55 dp[2][i][j]=max(dp[2][i][j],dp[1][j][0]+sum[i]); 56 } 57 } 58 for(int l=3;l<=n;l++) 59 for(int i=0;i<num;i++){ 60 if(a[i]&mp[l]) continue; 61 for(int j=0;j<num;j++){ 62 if(a[j]&mp[l-1]) continue; 63 if(a[j]&a[i]) continue; 64 for(int k=0;k<num;k++){ 65 if(a[k]&mp[l-2]) continue; 66 if(a[k]&a[j]) continue; 67 if(a[k]&a[i]) continue; 68 dp[l][i][j]=max(dp[l][i][j],dp[l-1][j][k]+sum[i]); 69 } 70 } 71 } 72 int ans=0; 73 for(int i=0;i<num;i++) 74 for(int j=0;j<num;j++) 75 ans=max(ans,dp[n][i][j]); 76 printf("%d\n",ans); 77 } 78 return 0; 79 }
标签:状态,int,压缩,memset,炮兵阵地,maxn,mp,sizeof,include 来源: https://www.cnblogs.com/pangbi/p/11886235.html