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

题目链接:http://poj.org/problem?id=1185

很裸的状压,考虑对于一行用二进制储存每一种的状态,但是状态太多了做不了。

观察到有很多状态都是不合法的,于是我们预处理出合法的状态,发现只有60种,然后随便DP一下就可以了。

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int N,M;
 6 char G[110][15];
 7 int s[65],cnt[65],scnt=0,ban[65];
 8 int f[110][65][65];
 9 int main(){
10     memset(ban,0,sizeof(ban));
11     memset(f,0,sizeof(f));
12     memset(cnt,0,sizeof(cnt));
13     memset(s,0,sizeof(s));
14     scanf("%d%d",&N,&M);
15     for(int i=1;i<=N;i++) scanf("%s",G[i]);
16     for(int i=1;i<=N;i++)
17         for(int j=0;j<M;j++)
18             if(G[i][j]=='H')
19                 ban[i]|=(1<<j);
20     int tmp=1<<M;
21     for(int i=0;i<tmp;i++){
22         bool flag=true;
23         for(int j=0;j<M;j++){
24             int tmp=((i&(1<<j))>0)+((i&(1<<j+1))>0)+((i&(1<<j+2))>0);
25             if(tmp>1){
26                 flag=false;
27                 break;
28             }
29         }
30         if(flag){
31             s[++scnt]=i;
32             for(int j=0;j<M;j++)
33                 if(i&(1<<j))
34                     cnt[scnt]++;
35         }
36     }
37     for(int i=1;i<=scnt;i++)
38         if((s[i]&ban[1])==0)
39             f[1][1][i]=cnt[i];
40     for(int i=1;i<=scnt;i++)
41         if((s[i]&ban[2])==0)
42             for(int j=1;j<=scnt;j++)
43                 if((s[i]&s[j])==0&&(s[j]&ban[1])==0)
44                     f[2][j][i]=max(f[2][j][i],f[1][1][j]+cnt[i]);
45     for(int i=3;i<=N;i++)
46         for(int j=1;j<=scnt;j++)
47             if((s[j]&ban[i-2])==0)
48                 for(int k=1;k<=scnt;k++)
49                     if((s[j]&s[k])==0&&(s[k]&ban[i-1])==0)
50                         for(int t=1;t<=scnt;t++)
51                             if((s[j]&s[t])==0&&(s[k]&s[t])==0&&(s[t]&ban[i])==0)
52                                 f[i][k][t]=max(f[i][k][t],f[i-1][j][k]+cnt[t]);
53     int Ans=0;
54     for(int i=1;i<=scnt;i++)
55         for(int j=1;j<=scnt;j++)
56             Ans=max(Ans,f[N][i][j]);
57     printf("%d\n",Ans);
58     return 0;
59 }

 

posted @ 2017-10-27 21:51  halfrot  阅读(161)  评论(0编辑  收藏  举报