题目链接

题目

题目描述

司令部的将军们打算在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. docker 容器ip查看及 网络配置区别

    本文为博主原创,未经允许不得转载: 1. 查看容器ip: 方法一:查看所有容器的ip docker inspect --format='{{.Name}} - {{range .NetworkSett ...

  2. 如何在 Photoshop 中制作 GIF 动画

    您可能已经使用过一些在线 gif 生成器来快速生成 gif 图像,但这些在线生成器无法提供与 Photoshop 相同的灵活性和结果. gif 就像您可以在 Photoshop 中创建的迷你动画.当你 ...

  3. IDE-常用插件

    2021-8-25_IDE-常用插件 1. 背景 提升编写代码的舒适度,提升开发效率 2. 常用插件列表 IDE EVal Reset 白嫖付费的golang编辑器,reset插件可以重置golang ...

  4. [转帖]Clickhouse单机及集群部署详解

    https://www.cnblogs.com/ya-qiang/p/13540016.html 一.ClickHouse简介 ClickHouse是近年来备受关注的开源列式数据库,主要用于数据分析( ...

  5. [转帖]OS Watcher (OSW)系统性能监控软件

    https://www.anbob.com/archives/1143.html OS Watcher简称OSW(oswbb),用于收集并归档操作系统cpu,memery,disk io,networ ...

  6. [转帖]Docker限制容器的资源

      docker在默认运行容器的情况下,是不会对运行的容器进行资源限制的,在自己的实验环境的话是随便你怎么弄的,不过在生产中是一定会对docker运行的容器进行资源限制的,如果不限制的话在生产中会带来 ...

  7. ESXi6.5+vCenter6.5 CentOS7 虚拟机启动之后控制台黑屏的解决方案

    公司最近搬迁服务器, 服务器的地址都发生了变化, 发现部分机器总是黑屏无法使用, 想了一个坚决办法使服务器能够连接设置地址后使用. 1. 控制台开机. 2. 注意在开机五秒之内打开web控制台, 然后 ...

  8. ELK运维文档

    Logstash 目录 Logstash Monitoring API Node Info API Plugins Info API Node Stats API Hot Threads API lo ...

  9. 通过Environment获取属性文件的值,竟然会调用到JNDI服务!!!

    一.背景介绍 某应用在压测过程机器cpu使用率超过80%,通过在线诊断工具进行CPU采样生成的火焰图,看到程序中频繁调用environment.getProperty()获取属性值,而其内部调用了Jn ...

  10. ThreadLocal源码解析及实战应用

    作者:京东物流 闫鹏勃 1 什么是ThreadLocal? ThreadLocal是一个关于创建线程局部变量的类. 通常情况下,我们创建的变量是可以被任何一个线程访问并修改的.而使用ThreadLoc ...