poj1185炮兵阵地--状态dp

炮兵阵地
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 17437   Accepted: 6669

Description

司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示: 

如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。 
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。 

Input

第一行包含两个由空格分割开的正整数,分别表示N和M; 
接下来的N行,每一行含有连续的M个字符('P'或者'H'),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。

Output

仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。

Sample Input

5 4
PHPP
PPHH
PPPP
PHPP
PHHP

Sample Output

6

Source

 
分析:
状态压缩即可,但是要注意不要判断错符合条件的式子:
check_raw:
num&(num<<1)==0 && num&(num<<2)==0
check_map:
num&map_num == num
check_two_lie:
a&b==0
 
代码:
  1 #include <iostream>
  2 #include <string.h>
  3 #include <stdio.h>
  4 #include <vector>
  5 using namespace std;
  6 
  7 const int maxn=10;
  8 int dp[102][1<<maxn][1<<maxn];
  9 int map_num[102];
 10 int sum_one[1<<maxn];
 11 
 12 vector<int>v[1<<maxn][1<<maxn];
 13 vector<int>::iterator it;
 14 
 15 void get_sum_one(int m)
 16 {
 17     int len=(1<<m);
 18     for(int i=0;i<len;i++)
 19     {
 20         int num=i;
 21         int sum=0;
 22         for(int j=1;j<=num;)
 23         {
 24             if(num&j)
 25                 sum++;
 26             j<<=1;
 27         }
 28         sum_one[i]=sum;
 29     }
 30 }
 31 
 32 bool check_raw(int num)
 33 {
 34     if((num&(num<<1)) || (num&(num<<2)))
 35         return false;
 36 
 37     return true;
 38 }
 39 
 40 bool check_map(int num,int mp_num)
 41 {
 42     if((num&mp_num)==num)
 43         return true;
 44 
 45     return false;
 46 }
 47 
 48 bool check_two_lie(int a,int b)
 49 {
 50     if(a&b)
 51         return false;
 52 
 53     return true;
 54 }
 55 
 56 void init(int m)
 57 {
 58     int len=(1<<m);
 59     for(int i=0;i<len;i++)
 60     {
 61         for(int j=0;j<len;j++)
 62         {
 63             v[i][j].clear();
 64         }
 65     }
 66     for(int i=0;i<len;i++)
 67     {
 68         if(!check_raw(i))
 69             continue;
 70         for(int j=0;j<len;j++)
 71         {
 72             if(!check_raw(j))
 73                 continue;
 74             for(int k=0;k<len;k++)
 75             {
 76                 if(!check_raw(k))
 77                     continue;
 78                 if(check_two_lie(i,j) && check_two_lie(i,k) && check_two_lie(j,k))
 79                     v[i][j].push_back(k);
 80             }
 81         }
 82     }
 83 }
 84 
 85 
 86 int main()
 87 {
 88     int n,m;
 89     //freopen("ac.txt","r",stdin);
 90     while(scanf("%d %d",&n,&m)!=EOF)
 91     {
 92 
 93         //check1(m);
 94         get_sum_one(m);
 95         init(m);
 96         char str;
 97         int num;
 98         for(int i=0;i<n;i++)
 99         {
100             int sum=0;
101             int k=m-1;
102             for(int j=0;j<m;j++)
103             {
104                 scanf("\n%c",&str);
105                 num=(str=='P'?1:0);
106                 sum+=num*(1<<k);
107                 k--;
108             }
109             map_num[i]=sum;
110         }
111        // check2(n);
112         int len=1<<m;
113         for(int j=0;j<len;j++)
114         {
115             if(check_raw(j) && check_map(j,map_num[0]))
116             {
117                 dp[0][j][0]=sum_one[j];
118             }
119         }
120         //check3(m);
121         for(int j=0;j<len;j++)
122         {
123             if(!check_raw(j) || !check_map(j,map_num[1]))
124                 continue;
125             for(int k=0;k<len;k++)
126             {
127                 if(!check_raw(k) || !check_map(k,map_num[0]))
128                 continue;
129                 if(check_two_lie(j,k))
130                 {
131                     if(dp[1][j][k]<dp[0][k][0]+sum_one[j])
132                     dp[1][j][k]=dp[0][k][0]+sum_one[j];
133                 }
134             }
135         }
136        // check4(m);
137         for(int i=2;i<n;i++)
138         {
139             for(int j=0;j<len;j++)
140             {
141                 if(!check_map(j,map_num[i-1]))
142                     continue;
143                 for(int k=0;k<len;k++)
144                 {
145                     if(!check_map(k,map_num[i-2]))
146                         continue;
147                     if(v[j][k].size()){
148                         for(int l=0;l<v[j][k].size();l++)
149                         {
150                             int xx=v[j][k][l];
151                             if(check_map(xx,map_num[i]))
152                                 if(dp[i][xx][j]<dp[i-1][j][k]+sum_one[xx])
153                             dp[i][xx][j]=dp[i-1][j][k]+sum_one[xx];
154                         }
155                     }
156                 }
157             }
158         }
159         int ans=0;
160         for(int j=0;j<len;j++)
161         {
162             for(int k=0;k<len;k++)
163             {
164                 if(ans<dp[n-1][j][k])
165                     ans=dp[n-1][j][k];
166             }
167         }
168         printf("%d\n",ans);
169     }
170     return 0;
171 }
View Code

 

 
posted @ 2014-04-08 18:53  悠悠我心。  阅读(230)  评论(0编辑  收藏  举报