POJ1185 [NOI2001] 炮兵阵地 (状压DP)

又是一道有合法性检测的状压题。

dp[i][j][k]表示第i行状态为j,i-1行状态为k时前i行放置的最大数量。

注意22行统计二进制数中1的个数时的巧妙方法。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int N,M;
 6 char map[110][20],num[70],top;
 7 int stk[70],cur[70];
 8 int dp[110][70][70];
 9 
10 bool check(int x){//判断该状态是否合法,横向检测相邻的1之间的距离不能小于3
11     if(x&(x<<1)) return 0;
12     if(x&(x<<2)) return 0;
13     return 1;
14 }
15 
16 void init(){//记录所有可能的合法状态,最多60种
17     top=0;
18     for(int i=0;i<(1<<M);i++)
19         if(check(i)) stk[top++]=i;
20 }
21 
22 int count(int x){//统计状态x的二进制中1的个数
23     int cnt=0;
24     while(x){
25         cnt++;
26         x&=(x-1);//很巧妙的求解方法 
27     }
28     return cnt;
29 }
30 
31 bool fit(int x,int k){
32     if(cur[k]&x) return 0;
33     return 1;
34 }
35 
36 int solve(){
37     int ans=0;
38     memset(dp,-1,sizeof(dp));
39     for(int j=0;j<top;j++){//初始化第一行状态
40         num[j]=count(stk[j]);//统计每个合法状态中1的个数
41         if(fit(stk[j],1)){
42             dp[1][j][0]=num[j];//第一行状态为j,上一行状态为第0个状态,即000000
43             ans=max(ans,dp[1][j][0]);
44         } 
45     }
46     for(int i=2;i<=N;i++)
47         for(int j=0;j<top;j++){
48             if(!fit(stk[j],i)) continue;
49             for(int k=0;k<top;k++){
50                 if(stk[j]&stk[k]) continue;
51                 for(int t=0;t<top;t++){
52                     if(stk[j]&stk[t]) continue;
53                     if(dp[i-1][k][t]==-1) continue;
54                     dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][t]+num[j]);
55                 }
56                 if(i==N) ans=max(ans,dp[i][j][k]);
57             }
58         }
59     return ans;
60 }
61 
62 int main(){
63     while(~scanf("%d%d",&N,&M)){
64         init();
65         for(int i=1;i<=N;i++) 
66             scanf("%s",map[i]+1);
67         for(int i=1;i<=N;i++){
68             cur[i]=0;
69             for(int j=1;j<=M;j++)
70                 if(map[i][j]=='H')
71                     cur[i]+=(1<<(j-1));
72         }
73         printf("%d\n",solve());
74     }
75     return 0;
76 }

 

posted @ 2022-06-25 09:57  YHXo  阅读(19)  评论(0编辑  收藏  举报