【POJ1185】炮兵阵地(状压DP)

题意:

思路:状压DP经典题

可以预处理下每一行内合法的状态,发现很少

所以转移时可以使用状态的编号而不是状态本身

DP时记录前两行状态的编号进行转移和判断

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cstring>
 6 #include<map>
 7 #include<set>
 8 #include<vector>
 9 #define INF 10000
10 #define MAXK 65
11 using namespace std;
12 int dp[110][MAXK][MAXK];
13 int a[MAXK],num[MAXK];
14 int b[110];
15 int n,m,K; 
16 char s[12];
17 
18 int main()
19 {
20     freopen("poj1185.in","r",stdin);
21     freopen("poj1185.out","w",stdout);
22     scanf("%d%d",&n,&m);
23     for(int i=1;i<=n;i++)
24     {
25         scanf("%s",s+1);
26         for(int j=1;j<=m;j++) 
27          if(s[j]=='H') b[i]+=(1<<(j-1));
28     }
29     int MAX=(1<<m)-1;
30     for(int i=0;i<=MAX;i++)
31      if((!(i&(i<<1)))&&(!(i&(i<<2)))) 
32      {
33        a[++K]=i; 
34        num[K]=0;
35        int x=i;
36        while(x>0)
37        {
38            num[K]+=(x%2);
39            x>>=1;
40        }
41      }
42      
43     for(int i=1;i<=n;i++)
44      for(int j=1;j<=K;j++)
45       for(int k=1;k<=K;k++) dp[i][j][k]=-INF; 
46       
47     for(int i=1;i<=K;i++)
48      if(!(b[1]&a[i])) dp[1][i][1]=num[i];
49      
50     for(int i=2;i<=n;i++)
51      for(int j=1;j<=K;j++)
52       if(!(b[i]&a[j]))
53       {
54           for(int k=1;k<=K;k++)
55            if(!(a[j]&a[k]))
56            {
57            for(int l=1;l<=K;l++)
58            {
59               if((a[l]&a[k])||(a[l]&a[j])) continue;
60               if(dp[i-1][k][l]==-INF) continue;
61               dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+num[j]);
62            }
63          }
64       }
65       
66    int ans=0;
67    for(int i=1;i<=K;i++)
68     for(int j=1;j<=K;j++) ans=max(ans,dp[n][i][j]);
69    printf("%d\n",ans);
70    return 0;    
71 }

 

posted on 2018-07-11 19:49  myx12345  阅读(137)  评论(0编辑  收藏  举报

导航