POJ 1185 炮兵阵地(状压dp)

 

http://poj.org/problem?id=1185

题意:

 

思路:

每一行最多只有10列,所以可以用二进制来表示每一行的状态。

d【i】【j】【k】表示第i行状态为k时,并且上一行状态为j时的最大炮兵数。

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<sstream>
  6 #include<vector>
  7 #include<stack>
  8 #include<queue>
  9 #include<cmath>
 10 #include<map>
 11 #include<set>
 12 using namespace std;
 13 typedef long long ll;
 14 typedef pair<int,int> pll;
 15 const int INF = 0x3f3f3f3f;
 16 const int maxn = 20+5;
 17 
 18 int n, m;
 19 
 20 char s[20];
 21 int st[105];
 22 int tmp[105];
 23 int num[105];
 24 int d[105][105][105];
 25 
 26 int calc(int x)
 27 {
 28     int tmp=0;
 29     while(x)
 30     {
 31         if(x&1)  tmp++;
 32         x>>=1;
 33     }
 34     return tmp;
 35 }
 36 
 37 int main()
 38 {
 39     //freopen("in.txt","r",stdin);
 40     while(~scanf("%d%d",&n, &m))
 41     {
 42         getchar();
 43         for(int i=1;i<=n;i++)
 44         {
 45             scanf("%s",&s);
 46             st[i]=0;
 47             for(int j=0;j<m;j++)
 48             {
 49                 st[i]=(st[i]<<1)|(s[j]=='P');
 50             }
 51         }
 52 
 53         int top=0;
 54         for(int i=0;i<(1<<m);i++)  //记录可行状态
 55         {
 56             if(!(i&(i<<1)) && !(i&(i<<2)))
 57             {
 58                 tmp[top]=i;
 59                 num[top]=calc(i);
 60                 top++;
 61             }
 62         }
 63 
 64         int ans=0;
 65         memset(d,-1,sizeof(d));
 66         for(int i=0;i<top;i++)  //第一行状态
 67         {
 68             if((st[1]|tmp[i])==st[1])   d[1][0][i]=num[i];
 69         }
 70 
 71         for(int i=2;i<=n;i++)
 72         {
 73             for(int j=0;j<top;j++)  //第i行状态
 74             {
 75                 if((st[i]|tmp[j])!=st[i])  continue;
 76 
 77                 for(int k=0;k<top;k++)  //第i-1行状态
 78                 {
 79                     if((st[i-1]|tmp[k])!=st[i-1])  continue;
 80                     if(tmp[j]&tmp[k])  continue;  //和第i行有冲突
 81 
 82                     for(int t=0;t<top;t++)  //第i-2行状态
 83                     {
 84                         if(i>2)
 85                         {
 86                             if((st[i-2]|tmp[t])!=st[i-2])  continue;
 87                             if(tmp[t]&tmp[k])  continue;
 88                             if(tmp[t]&tmp[j])  continue;
 89                         }
 90 
 91                         d[i][k][j]=max(d[i][k][j],d[i-1][t][k]+num[j]);
 92                     }
 93                 }
 94             }
 95         }
 96         
 97         for(int i=0;i<top;i++)
 98             for(int j=0;j<top;j++)
 99             ans=max(ans,d[n][i][j]);
100         printf("%d\n", ans);
101     }
102     return 0;
103 }

 

posted @ 2017-06-29 09:50  Kayden_Cheung  阅读(186)  评论(0编辑  收藏  举报
//目录