P2704 [NOI2001] 炮兵阵地 题解

news2024/10/5 18:25:50

P2704

  • 题目
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
      • 提示
  • 解题思路
    • 分析
    • Code
      • 更多方法


题目

原题链接

题目描述

司令部的将军们打算在 N × M N\times M N×M 的网格地图上部署他们的炮兵部队。

一个 N × M N\times M N×M 的地图由 N N N M M M 列组成,地图的每一格可能是山地(用 H \texttt{H} H 表示),也可能是平原(用 P \texttt{P} P 表示),如下图。

在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:

如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。

图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。

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

输入格式

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

接下来的 N N N 行,每一行含有连续的 M M M 个字符,按顺序表示地图中每一行的数据。

输出格式

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

样例 #1

样例输入 #1

5 4
PHPP
PPHH
PPPP
PHPP
PHHP

样例输出 #1

6

提示

对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 100 1 \leq N\le 100 1N100 1 ≤ M ≤ 10 1 \leq M\le 10 1M10,保证字符仅包含 PH

解题思路

分析

由于每一行都受上两行的状态的影响,所以我们需要开三维数组。
我们令 1 1 1 表示此地放了阵地, 0 0 0 则表示没有。
定义 f [ i ] [ s ] [ s 1 ] f[i][s][s1] f[i][s][s1] 表示当前在第 i i i 行,本行状态为 s s s,上一行状态为 s 1 s1 s1 时最多有几个阵地。
则循环枚举,有:

f[i][s][s1]=max(f[i][s][s1],f[i-1][s1][s2]+a[s]);

其中 s 2 s2 s2 为上两行状态, a [ s ] a[s] a[s] 表示当状态为 s s s 时放了几个阵地。
但必须满足:

  1. 状态 s , s 1 , s 2 s,s1,s2 s,s1,s2 均是合法状态。
  2. s 2 s2 s2 不影响 s , s 1 s,s1 s,s1 s 1 s1 s1 不影响 s s s

所以纯暴力的代码就已经出来了,不过:
时间复杂度: O ( n m 2 8 m ) O(nm^28^m) O(nm28m)
空间复杂度: O ( n 4 m ) O(n 4^m) O(n4m)
好吧,根本不会炸

考虑优化:

  1. 对于每个 a [ i ] a[i] a[i],可以预处理解决。
  2. 对于每个状态 s s s 本身是否合法可以预处理。
  3. 对于每个状态 s s s 的下一行有几个合法状态可以预处理。
  4. 对于每个地形,可以用二进制来表示, 1 1 1 为山地, 0 0 0 为平地。判断是 & 一下就行了。
  5. 第一维的 i i i 可以滚动掉。

对于 1
很简单:

inline int ga(int x)
{
	int cnt=0;
	while(x>0)
	{
		if(x&1)
			cnt++;
		x>>=1;
	}
	return cnt;
}

对于 2

inline bool check(int x)
{
	return !(((x>>2)&x)|(x&(x>>1)));
}
	for(int i=0;i<(1<<m);i++)
		if(check(i))
			s.push_back(i);

即每两个 1 1 1 之间至少隔两个 0 0 0
对于 3

	int len=s.size();
	for(int i=0;i<len;i++)
		for(int j=0;j<len;j++)
			if(!(s[i]&s[j]))
				Q[s[i]].push_back(s[j]);

对于 4
同样很简单:

for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>c;
			g[i]=(g[i]<<1)+(c=='H');
		}
	}

Code

 #include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL);
using namespace std;
const int N=1<<10;
vector<int>s;
vector<int>Q[N];
int n,m,f[101][N][N],g[200],a[N];
char c;
inline bool check(int x)
{
	return !(((x>>2)&x)|(x&(x>>1)));
}
inline int ga(int x)
{
	int cnt=0;
	while(x>0)
	{
		if(x&1)
			cnt++;
		x>>=1;
	}
	return cnt;
}
signed main()
{
	IOS;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>c;
			g[i]=(g[i]<<1)+(c=='H');
		}
	}
	for(int i=0;i<(1<<m);i++)
		if(check(i))
			s.push_back(i),a[i]=ga(i);
	int len=s.size();
	for(int i=0;i<len;i++)
		for(int j=0;j<len;j++)
			if(!(s[i]&s[j]))
				Q[s[i]].push_back(s[j]);
	int Y=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<len;j++)
		{	
			Y++;
			int S=s[j];
			if(!(g[i]&S))
			{
				int L=Q[S].size();
				for(int k=0;k<L;k++)
				{
					int S1=Q[S][k];
					int Le=Q[S1].size();
					for(int u=0;u<Le;u++)
					{
						int S2=Q[S1][u];
						if((S&S2)||(S1&g[i-1])||(S2&g[i-2]))
							continue;
						f[i][S][S1]=max(f[i][S][S1],f[i-1][S1][S2]+a[S]);
					}
				}
			}
		}
	}
	int ans=0;
	for(int i=0;i<len;i++)
		for(int j=0;j<Q[s[i]].size();j++)
			ans=max(ans,f[n][s[i]][Q[s[i]][j]]);
	cout<<ans;
	return 0;
}

空间复杂度: O ( 4 m ) O(4^m) O(4m)
时间复杂度: O ( n 8 m ) O(n8^m) O(n8m)

而由于优化过后了,时间复杂度远远跑不满,实际复杂度约为: O ( 60 × [ 20 , 40 ] 2 × n ) O(60\times [20,40]^2 \times n) O(60×[20,40]2×n)

更多方法

更多方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1258241.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android 12 打开网络ADB并禁用USB连接ADB

平台 RK3588 Android 12 Android 调试桥 (adb) Android 调试桥 (adb) 是一种功能多样的命令行工具&#xff0c;可让您与设备进行通信。adb 命令可用于执行各种设备操作&#xff0c;例如安装和调试应用。adb 提供对 Unix shell&#xff08;可用来在设备上运行各种命令&am…

代码块02使用细节-Java

代码块02使用细节 四、使用细节1、static代码块/静态代码块&#xff0c;随着类的加载而执行&#xff0c;且只执行一次2、 类什么时候被加载 [重要 ! ]案例演示&#xff1a;static代码块 3、普通代码块&#xff0c;在创建对象实例时&#xff0c;会被隐式的调用。案例演示&#x…

2023 中国 Serverless 用户调查,邀您填写!

当前云计算已成为数字时代的基础设施&#xff0c;支撑众多企业进行数字化转型升级。随着企业上云的范围更加广泛&#xff0c;国内云计算正在迈向云原生时代。Serverless技术因其以应用为中心、屏蔽底层复杂逻辑&#xff0c;灵活扩展&#xff0c;按需取用的特点&#xff0c;已经…

【解决方案】安科瑞智能照明系统在福建二建大厦项目上的研究与应用

【摘要】&#xff1a;智能化已经成为当今建筑发展的主流技术、涵盖从空调系统、消防系统到安全防范系统以及完善的计算机网络和通信系统。但是长期以来、智能照明在国内一直被忽视、大多数建筑物仍然沿用传统的照明控制方式、部分智能大厦采用楼宇自控&#xff08;BA&#xff0…

如何在vs2017及以前版本(vs2010、vs2015)上添加 添加类型库中的MFC类

有时候当我们新建MFC工程需要使用到微软的一些自带控件&#xff0c;如播放视频要用到Windows media player控件&#xff0c;这时&#xff0c;我们可以通过添加“ActiveX控件中的mfc类(A)”这一选项. 还有有时候我们需要用到“类型库中的MFC类(T)及“MFC ODBC使用者(O)”。那我们…

如何获取抖音订单API数据接口?

在开放平台中&#xff0c;每个API接口都有相应的文档说明和授权机制&#xff0c;以确保数据的安全性和可靠性。开发者可以根据自己的需求选择相应的API接口&#xff0c;并根据文档说明进行调用和使用。 开放平台API接口是一套REST方式的开放应用程序编程接口&#xff0c;它…

NX二次开发UF_CURVE_create_arc_point_center 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_create_arc_point_center Defined in: uf_curve.h int UF_CURVE_create_arc_point_center(tag_t point, tag_t center, UF_CURVE_limit_p_t limit_p [ 2 ] , tag_t support…

Clion取消double shift(按两下shift键)全局搜索

Clion 取消 double shift&#xff08;按两下 shift 键&#xff09;全局搜索。 如下图所示打开 setting。 点击 advanced setting&#xff0c;搜索 disable&#xff0c;取消勾选左侧复选框&#xff0c;点击 ok。

Linux进程状态(僵尸进程,孤儿进程)+进程优先级+进程调度与切换

Linux进程状态[僵尸进程,孤儿进程]进程优先级 一.进程状态1.进程排队2.教材上对于进程状态的描述:1.阻塞挂起 3.Linux下具体的进程状态:1.Linux下的进程状态数组2.R3.S:可终止睡眠---浅度睡眠1.补充:前台进程和后台进程2.一种"奇怪"的现象 4.D:不可终止睡眠---深度睡…

ESXi 添加虚拟闪存 无可选设备问题排查

虚拟内存是计算机系统中的一种技术&#xff0c;它可以将计算机硬盘的一部分空间作为临时存储器来使用。当计算机的物理内存&#xff08;RAM&#xff09;不足时&#xff0c;操作系统可以将部分数据从内存移至硬盘的虚拟内存空间中&#xff0c;以释放内存供其他程序使用。虚拟内存…

C++基础 -4- C/C++混合编程

引用格式(图片代码段呈现) extern "C" {#include "string.h" }代码验证 &#xff08;分别使用了C/C 的标准输出&#xff09; #include "iostream"using namespace std;extern "C" { #include "stdio.h" #include "…

Arthas 使用

Arthas是阿里巴巴开源的Java诊断工具&#xff0c;采用命令行交互的形式进行问题的定位与诊断。它能够帮助你. 解决以下问题&#xff1a; 这个类从哪个 jar 包加载的&#xff1f;为什么会报各种类相关的 Exception&#xff1f;我改的代码为什么没有执行到&#xff1f;难道是我…

卸载软件最最最彻底的工具——Uninstall Tool

卸载软件最最最彻底的工具——Uninstall Tool Uninstall Tool 是一款功能强大的专业卸载工具。针对一些普通卸载不彻底的问题&#xff0c;它可以做到最优&#xff0c;比如Matlab等软件的卸载难的问题也可以较好地解决。 它比 Windows 自带的“添加/删除程序”功能快 3 倍&…

深度学习:全面了解深度学习-从理论到实践

深度学习&#xff1a;全面了解深度学习-从理论到实践 摘要&#xff1a;本文旨在为读者提供一份全面的深度学习指南&#xff0c;从基本概念到实际应用&#xff0c;从理论数学到实践技术&#xff0c;带领读者逐步深入了解这一领域。我们将一起探讨深度学习的历史、发展现状&#…

算法通关第十七关青铜挑战——原来贪心如此简单(什么是贪心思想and经典例题分析)

大家好&#xff0c;我是怒码少年小码。 一转眼&#xff0c;又到了11月末尾了&#xff0c;莫名感觉今年真的很快&#x1f602;。今天的主角是贪心。 贪心的思想非常不好解释&#xff0c;而且越使用权威的语言解释越难懂。而且做题的时候根据自己的理解可能直接做出来&#xff…

Ubuntu 22.03 LTS 安装deepin-terminal 分屏

安装 源里面自带了这个软件&#xff0c;可以直接装 sudo apt install deepin-terminal 启动 按下Win键&#xff0c;输入deep即可快速检索出图标&#xff0c;点击启动 效果 分屏 CtrlShiftH 水平分割 CtrlShiftJ 垂直分割 最多分割成四个小窗口&#xff0c;鼠标点击可以切换…

C#常见的设计模式-结构型模式

引言 设计模式是软件工程中用于解决常见问题的可复用解决方案。在C#编程中&#xff0c;常见的设计模式具有广泛的应用。本篇博客将重点介绍C#中常见的结构型设计模式&#xff0c;包括适配器模式、装饰器模式、代理模式、组合模式和享元模式。 目录 引言1. 适配器模式(Adapter …

便利高效双赢:无人机油气管道巡检全面升级

我国庞大的油气管道网络&#xff0c;包括原油、成品和天然气管道&#xff0c;因为地理区域广泛、建设年代久远、安全事故频发等现实因素&#xff0c;对管道的安全巡护与管理提出了更高的需求。在这一背景下&#xff0c;传统的人工巡护方式显然已经难以满足对高、精、准的要求。…

【受体 + 二系统 】

GPCR A级超家族家庭成员/基因评论胺受体受体的六个亚家族总共包括45个基因&#xff08;其中4个是假基因&#xff09;;这六个亚家族是5-羟色胺&#xff08;5-HT&#xff0c;血清素&#xff09;受体&#xff08;13个基因&#xff09;&#xff0c;多巴胺受体&#xff08;5个基…

瑞数五代ast反混淆笔记一

第一部分 瑞数五代ast反混淆笔记一 文章目录 前言一、分析第一层js文件二、转换为switch-case三、效果图总结 前言 瑞数五代的反混淆做了很久了&#xff0c;当时写的很复杂&#xff0c;也没有记笔记&#xff0c;现在看代码都看不懂了&#xff0c;重新归顺下逻辑思路 一、分析第…