题目链接

题目

题目描述

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



如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。

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

输入描述

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

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

输出描述

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

示例1

输入

5 4
PHPP
PPHH
PPPP
PHPP
PHHP

输出

6

题解

知识点:状压dp。

一道经典的状压dp。考虑一行一行放,用一个整数表示一行的炮兵状态,\(1\) 表示放了,\(0\) 表示没放;同样,用一个整数表示一行地图状态,高地为 \(1\) ,平原为 \(0\) ,这样设置 \(01\) 非常方便。

先预处理出一行的合法状态,满足 (i & (i << 1)) || (i & (i << 2)) == 1 都是非法的,因为相邻两格不能放,其余都是合法的,存入合法状态数组 \(v\)。

开始递推,设 \(dp[i][st1][st2]\) 表示第 \(i\) 行,上一行状态是 \(st1\) ,上两行状态是 \(st2\)。枚举这三个状态,再枚举第 \(i-1\) 行的上两行状态 \(st3\)。满足 st1 & dt[i] == 1 则 \(st1\) 不合法,因为不能放在高地;满足 st2 & dt[i-1] || st1 & st2 == 1 ,则 \(st2\) 不合法,因为不能放在高地,且不能和第 \(i-1\) 行冲突;满足 st3 & dt[i-2] || st3 & st1 || st3 & st2 == 1 ,则 \(st3\) 不合法,因为不能放在高地,且不能和第 \(i-1\) 和 \(i-2\) 行冲突。最后全都合法,有转移方程:

\[dp[i][st1][st2] = \max(dp[i][st1][st2], dp[i - 1][st2][st3] + num[st1]),num[st1] = \rm{popcount}(st1)
\]

每次转移就记录一次答案,可以最后少写一个三重循环找答案。

可以用状态编号优化空间,而不用状态本身作为下标。

时间复杂度 \(O(n \cdot 10^6)\) ,因为跑不满实际上 \(2^m\) 只有 \(65\) 。

空间复杂度 \(O(n \cdot 10^4)\)

代码

#include <bits/stdc++.h>

using namespace std;

int dt[107];
int dp[107][107][107];
vector<int> v, num; int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
for (int i = 2;i <= n + 1;i++) {
for (int j = 1;j <= m;j++) {
char ch;
cin >> ch;
if (ch == 'H') dt[i] |= 1 << (j - 1);
}
}
for (int i = 0;i < (1 << m);i++) {
if ((i & (i << 1)) || (i & (i << 2))) continue;
v.push_back(i);
num.push_back(__builtin_popcount(i));
}
int ans = 0;
for (int i = 2;i <= n + 1;i++) {
for (int j = 0;j < v.size();j++) {
int st1 = v[j];
if (st1 & dt[i]) continue;
for (int k = 0;k < v.size();k++) {
int st2 = v[k];
if (st2 & dt[i - 1]) continue;
if (st1 & st2) continue;
for (int l = 0;l < v.size();l++) {
int st3 = v[l];
if (st3 & dt[i - 2]) continue;
if ((st3 & st1) || (st3 & st2)) continue;
dp[i][j][k] = max(dp[i][j][k], dp[i - 1][k][l] + num[j]);
}
ans = max(ans, dp[i][j][k]);
}
}
}
cout << ans << '\n';
return 0;
}

NC16886 [NOI2001]炮兵阵地的更多相关文章

  1. [洛谷P2704] [NOI2001]炮兵阵地

    洛谷题目链接:[NOI2001]炮兵阵地 题目描述 司令部的将军们打算在NM的网格地图上部署他们的炮兵部队.一个NM的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示), ...

  2. C++ 洛谷 P2704 [NOI2001]炮兵阵地

    P2704 [NOI2001]炮兵阵地 没学状压DP的看一下 此题意思很简单,如下图,就是十字架上的不能有两个点放炮兵. 在做此题前,先做一下玉米田 玉米田题解 分析: 而m即一行的个数小于等于10, ...

  3. P2704 [NOI2001]炮兵阵地 (状压DP)

    题目: P2704 [NOI2001]炮兵阵地 解析: 和互不侵犯一样 就是多了一格 用\(f[i][j][k]\)表示第i行,上一行状态为\(j\),上上行状态为\(k\)的最多的可以放的炮兵 发现 ...

  4. 洛谷P2704 [NOI2001]炮兵阵地 [状压DP]

    题目传送门 炮兵阵地 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图 ...

  5. [Poj1185][Noi2001]炮兵阵地(状压dp)

    炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 29476   Accepted: 11411 Descriptio ...

  6. P2704 [NOI2001]炮兵阵地

    题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图.在每一格平原地形上最 ...

  7. [NOI2001]炮兵阵地 【状压DP】

    #\(\color{red}{\mathcal{Description}}\) \(Link\) 司令部的将军们打算在\(N \times M\)的网格地图上部署他们的炮兵部队.一个\(N \time ...

  8. [NOI2001]炮兵阵地 状压DP

    题面: 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图.在每一格平原地形上最多 ...

  9. Luogu 2704 [NOI2001]炮兵阵地

    唔,想到了状压之后就不会了……实在是菜 考虑压两行,设$f_{i, j, k}$表示当前到第$i$行,上一行是$j$状态,前一行是$k$状态的最多能放的炮兵的数量. 发现第一维还可以滚掉,好像可以转移 ...

  10. 洛谷2704 [NOI2001]炮兵阵地

    题目戳这里 Solution 状压DP很好的入门题,用熟练位运算貌似也没那么难. 首先分析一下题目: 看见n=100,m=10,立马就想到了状压,看起来也像DP,所以我们还是采用行号为阶段的状压DP. ...

随机推荐

  1. kibana上执行ES DSL语言查询数据并查看表结构与数据、删除索引、查看文件大小

    转载请注明出处: 1.kibana 上执行DSL 语言: 在kibana 中找到 Dev Tools,并双击打开,就可以进入执行DSL得执行页面了 执行DSL,示例如图: 2.在kibana上查看ES ...

  2. 07-verilog & sytem verilog

    一.数据类型 二值逻辑变量 bit 不赋值的时候,变量初始默认为0 x或z的值会转变为0 bit vector--bit矢量 bit [msb,lsb] variable_name = [initia ...

  3. 如何查找SpringBoot应用中的请求路径(不使用idea)

    背景 昨天有个同事向我咨询某个接口的物理表是哪个,由于公司业务较多.这块业务的确不是我负责的,也没有使用idea不能全局搜索(eclipse搜不到jar内的字符串),也就回复了不清楚. 除了自己写代码 ...

  4. [转帖]Grafana+influxdb+ntopng简易网络流量分析展示系统

    Grafana逼格高,所以用它展示ntopng的数据 >_< 一,ntopng 根据官网资料 https://www.ntop.org/ntop/ntopng-influxdb-and-g ...

  5. [转帖]Shell字符串拼接(连接、合并)

    http://c.biancheng.net/view/1114.html 在脚本语言中,字符串的拼接(也称字符串连接或者字符串合并)往往都非常简单,例如: 在 PHP 中,使用.即可连接两个字符串: ...

  6. [转帖]Web性能优化工具WebPageTest(二)——性能数据

    Web性能优化工具WebPageTest(二)--性能数据 https://www.cnblogs.com/strick/p/6681692.html 在前一篇<配置>完成后,点击&quo ...

  7. [转帖]ELF文件详解

    一.ELF概述 1.ELF的定义 ELF(Executable and Linkable Format)文件是一种目标文件格式,常见的ELF格式文件包括:可执行文件.可重定位文件(.o).共享目标文件 ...

  8. Redis 的简单学习与整理

    Redis 的简单学习与整理 背景 最近一直进行Redis性能调优和高可用的课题 但是不管什么课题,第一步应该是学习与使用redis 之前总结过 rdb 与 rdr 分析 键值对等内容. 但是发现想要 ...

  9. zabbix 6.0 官方文档

    Choose your platform   ZABBIX VERSION 6.0 LTS 5.4 5.0 LTS 4.0 LTS OS DISTRIBUTION Red Hat Enterprise ...

  10. Ant Design Vue封装a-drawer

    1.创建子组件 <template> <a-drawer :title="drawerInfo.customTitle" :placement="pla ...