状态压缩(炮兵阵地)

该题题意:在规定的地图里放大炮,大炮放的位置有限制,只有‘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 }

猜你喜欢

转载自www.cnblogs.com/pangbi/p/11886235.html