#zYDPybttg050404. 1595:炮兵阵地

1595:炮兵阵地

好的,我将这道题整理为清晰的题面格式,并补充样例解释、数据范围与时空限制:


题目描述

原题来自:NOI 2001

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

攻击范围:以炮兵所在位置为中心,横向左右各两格,纵向上下各两格,共覆盖横竖各 55 格(即曼哈顿距离 2\le 2 且在同一行或同一列,但不包括斜对角?实际上是十字形横向2格、纵向2格,共 5×55\times 5 的十字形,但注意图中是横向左右2格、纵向上下2格,共 5555 列的十字形,但实际影响范围是上下左右各两格,所以总共影响 44 个方向各 22 格加上自身,共 99 个格子?图例中黑色区域为横向左右2格、纵向上下2格,不包括斜角,所以是十字形,总共 1+2+2+2+2=91+2+2+2+2=9 格?我们确认:横向左右2格(共5列),纵向上下2格(共5行),所以是十字形,共 5+51=95+5-1=9 格(因为中心重叠)。

现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。


输入格式

第一行包含两个由空格分割开的正整数,分别表示 NNMM

接下来的 NN 行,每一行含有连续的 MM 个字符(P 或者 H),中间没有空格。按顺序表示地图中每一行的数据。


输出格式

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


样例

样例输入

5 4
PHPP
PPHH
PPPP
PHPP
PHHP

样例输出

6

样例解释

地图如下(P 平原可放,H 山地不可放):

P H P P
P P H H
P P P P
P H P P
P H H P

炮兵攻击范围是横向左右各2格、纵向上下各2格。

我们需要在平原上放置炮兵,使得任何两个炮兵不在彼此的攻击范围内。

一种最优放置方案(用 X 表示炮兵):

X H X P
P P H H
P P P X
X H P P
P H H X

即:

  • 第1行:第1列、第3列
  • 第3行:第4列
  • 第4行:第1列
  • 第5行:第4列

66 个炮兵。


数据范围

对于全部数据:

  • N100N \le 100
  • M10M \le 10

时空限制

  • 时间:1000 ms1000 \text{ ms}
  • 内存:524288 KB524288 \text{ KB}

提示
此题为 状态压缩 DP 经典题(NOI 2001)。

特点:炮兵的攻击范围涉及两行,所以状态转移时需要知道前两行的状态。

状态设计

  • 用二进制数表示一行的炮兵放置情况:11 表示放炮兵,00 表示不放;
  • 状态必须满足:
    1. 一行内炮兵不能互相攻击:即任意两个 11 之间至少间隔 2200(因为攻击范围左右各 22 格);
    2. 炮兵只能放在平原上(P),不能放在山地(H);
    3. 相邻两行之间,同一列不能同时有 11(因为上下攻击范围 22 格,所以上下相邻两行不能有同一列都有炮兵);
    4. 隔行之间,同一列也不能同时有 11(因为攻击范围上下各两格,所以第 ii 行和第 i+2i+2 行的同一列不能同时有炮兵)。

dp[i][s1][s2]dp[i][s1][s2] 表示处理到第 ii 行,第 ii 行状态为 s1s1,第 i1i-1 行状态为 s2s2 时,前 ii 行最多能放的炮兵数量。

转移方程:

$$dp[i][s1][s2] = \max_{s3} \{ dp[i-1][s2][s3] + \text{popcount}(s1) \}$$

条件:

  1. s1s1 内部合法(无相邻两个 11 距离 <3<3);
  2. s1s1 与地图第 ii 行兼容(s1s111 必须对应平原);
  3. s1s1s2s2 兼容(同一列不能同时为 11);
  4. s1s1s3s3 兼容(同一列不能同时为 11)。

初始化:dp[0][0][0]=0dp[0][0][0] = 0

最终答案:

maxs1,s2dp[N][s1][s2]\max_{s1,s2} dp[N][s1][s2]

优化

  • 预处理所有合法行状态(满足间隔至少两个 00);
  • 预处理状态间的兼容性(两两状态同一列不能同时为 11);
  • 由于 M10M \le 10,合法状态数较少(约 6060 个),三重循环可接受。

复杂度:O(N×S3)O(N \times |S|^3)S|S| 为合法状态数,可以过。