【POJ1185】炮兵阵地 状压DP

感觉总是被一些SB错误所困扰。。。

差不多还是(模板题)注意数组空间的大小,和对于合法状态的判断。

f[i][j][k]=max(f[i][k][j],f[i-1][l][k]+num[j]) (f[i][j][k]表示:第i行状态为k且满足第i-1行状态为j的合法方案数,num[i]是状态i所包含的方案数)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 #define N 110
 7 #define M 70
 8 #define inf 0x7fffffff
 9 int map[N],can[M],num[N];
10 int   dp[N][M][M];
11 int n,m,T,cnt,ans;
12 bool ju1(int x)
13 {
14     if ((x&(x<<1)) || (x&(x<<2))) return false;
15     return true;
16 }
17 bool ju2(int x,int y)
18 {
19     return map[x]&can[y];
20 }
21 int count(int x)
22 {
23     int sum=0;
24     while (x)
25     {
26         if (x&1) sum++;
27         x>>=1;
28     }
29     return sum;
30 }
31 int main()
32 {
33     //scanf("%d",&T);
34     char s;
35     while (~scanf("%d%d",&n,&m))
36     {
37         //scanf("%d%d",&n,&m);
38         memset(dp,-1,sizeof(dp));
39         memset(map,0,sizeof(map));
40         memset(can,0,sizeof(can));
41         memset(num,0,sizeof(num));
42         ans=-inf;
43         cnt=0;
44         for (int i=1;i<=n;i++)
45         {
46             getchar();
47             for (int j=1;j<=m;j++)
48             {
49                 scanf("%c",&s);
50                 if (s=='H') map[i]+=(1<<(j-1));    
51             }
52         }
53         for (int i=0;i<(1<<m);i++)
54             if (ju1(i)) can[++cnt]=i;
55         for (int i=1;i<=cnt;i++)
56         {
57             num[i]=count(can[i]);
58             if (!ju2(1,i))    dp[1][1][i]=num[i];
59         }
60         for (int i=2;i<=n;i++)//line
61         {
62             for (int j=1;j<=cnt;j++)//now
63             {
64                 if (ju2(i,j)) continue;
65                 for (int k=1;k<=cnt;k++)// before last
66                 {
67                     if (can[j]&can[k]) continue;
68                     for (int l=1;l<=cnt;l++) //last
69                     {
70                         if (can[l]&can[j]) continue;
71                         if (dp[i-1][k][l]==-1) continue;
72                         dp[i][l][j]=max(dp[i][l][j],dp[i-1][k][l]+num[j]);    
73                         //ans=max(ans,dp[i][l][j]);
74                     }
75                 }
76             }
77         }
78         for (int i=1;i<=cnt;i++)
79             for (int j=1;j<=cnt;j++)
80                 ans=max(ans,dp[n][i][j]);
81     printf("%d\n",ans);
82     }
83     return 0;
84 }
View Code

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

posted @ 2016-03-30 10:21  DMoon  阅读(180)  评论(0编辑  收藏  举报