题解:P14065 [PO Final 2022] 对弈 / Laserschack

news/2025/10/10 20:23:27/文章来源:https://www.cnblogs.com/Noivelist/p/19133798

题目传送门

先警示后人:
我在看题目的时候看成了 \(1 \le r,c \le 4000\)
然后被迫想了一个 \(\operatorname{O}(\operatorname{RC} \ \operatorname{log} \ \operatorname{RC})\) 发现好像有点玄
最后乱加一堆优化跑爆了只能重写


正解:

  • 对于这个数组考虑 二维 转 一维 ,静态数组存不下
    如果喜欢用动态二维数组自然是很好的()
  • 算法上考虑两遍 BFS 直接秒了,下面开始介绍思路

第一遍 BFS:

我们多源 BFS 对所有 R 进行扩展
更新图上每个点最早被烟雾覆盖的时间 \(\operatorname{time[\ ]}\)
BFS 的特性可以保证这样遍历到的每个点确实是正确的
\(\operatorname{O(RC)}\)

第二遍 BFS:

从 A 开始或从 K 开始都无所谓,我喜欢反图就从 K 开始了

  • 我们的目标:
    找到所有合法路径(即能从 A 到达 K 的路径)最晚被烟雾碰到的那条路,并且求出这条路上最小的 \(\operatorname{time[\ ]}\)

  • 实现方式:
    从 K 开始遍历四个方向

    如果找到了边界,就 break
    如果找到了 o ,说明找到一条子路了,就判断当前子路存的 path_time[ ] 是否小于当前手里搜出来的最小断点,如果是,就拿手里这个更新这个子路的 path_time[ ]
    如果找到了 A ,说明走通了一条合法路径,我们拿手里的最小断点直接去 \(\max(\operatorname{ans,current})\)

    而这个 BFS 的队列的存储要使用大根堆的优先队列来尽可能的贪心,就像 dijkstra 选取最小边来扩展
    我们从队列里面拿出任意一个点的时候,将他的最早断点与此时的 ans 对比,如果这个最早断点早于 ans ,那么直接可以 continue
    这时 \(\operatorname{O(RC \ log \ RC)}\)

  • 正确性简证:
    激光不经过任何烟雾,从而攻击到国王。
    也就是所有 A 到 K 的合法路径上都存在烟雾,求这个最早的时间
    转换成不以时间为变量,求所有路径上最早断点最晚的路径,当这个路径被遮住是,其他所有路径也早就被遮住

细节都在代码里了
注释清晰,码风优良


\(\mathbb {\LARGE C \large _O \ \Large ^D \normalsize _E}\)

#include<bits/stdc++.h>using namespace std;const int N = 4002;
const int dx[5] = {0, 1, -1, 0, 0};
const int dy[5] = {0, 0, 0, 1, -1};struct SMOKE {int x, y;
};queue< SMOKE >R;//存储R的坐标,用于多源BFS预处理图 int r, c, in_x, in_y, pth_min;//in_x,in_y存国王的坐标 
int a[N << 4], SMoke_TIme[N << 4], vis[N << 4]; //a存图; SMoke_TIme存烟雾的时间层; vis存当前点(只有镜子才会有)的最早断点 
int ans = 0;
int x , y, xx, yy, v;void input(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin >> r>> c;for(int i = 1; i <= r; i++){for(int j = 1; j <= c; j++){SMoke_TIme[c * (i - 1) + j] = -1;char ch;cin >> ch;if(ch == 'o') a[c * (i - 1) + j] = 4;if(ch == '.') a[c * (i - 1) + j] = 0;if(ch == 'A') a[c * (i - 1) + j] = 1;if(ch == 'K') {a[c * (i - 1) + j] = 2;in_x = i;in_y = j;//存储国王位置 }if(ch == 'R') {a[c * (i - 1) + j] = 3;R.push(SMOKE{i, j});//烟雾初始位置入队保存 SMoke_TIme[c * (i - 1) + j] = 0;}}}
}void output(){cout << ans << endl;
}void BFS(){//多源BFS预处理图的时间层 while( !R.empty()){x = R.front().x;y = R.front().y;R.pop();for(int i = 1; i <= 4; i++){//四个方向扩散 xx = x + dx[i];yy = y + dy[i];if(xx < 1 or yy < 1 or xx > r or yy > c or SMoke_TIme[c * (xx - 1) + yy] != -1)continue;//边界条件//BFS能保证每个点搜到的时候都是距离他最近的烟雾为祖先//也就是能保证SMoke_TIme最小 SMoke_TIme[c * (xx - 1) + yy] = SMoke_TIme[c * (x - 1) + y] + 1;//是自己祖先的下一秒 R.push(SMOKE{xx, yy});}}
}struct path{int x, y;int v;//到这个镜子的这条路径上的最早阻断点,也就是这条路最早失效的时间 bool operator <(const path &other)const {return v >= other.v;//优先队列取出当前最优解(就是最晚被干掉的合法路径) }
};priority_queue< path >q;void solve_BFS(){//从国王位置倒着搜所有合法路径 for(int i = 1; i <= 4; i++){xx = in_x;yy = in_y;pth_min = SMoke_TIme[c * (xx - 1) + yy];while(true){xx += dx[i];yy += dy[i];if(xx < 1 or yy < 1 or xx > r or yy > c)break;//边界条件判断 if(a[c * (xx - 1) + yy] == 3) break;//剪枝 pth_min = min(pth_min, SMoke_TIme[c * (xx - 1) + yy]);if(a[c * (xx - 1) + yy] == 4){//遇到镜子就停止这个方向的初始化vis[c * (xx - 1) + yy] = max(vis[c * (xx - 1) + yy], pth_min);q.push(path{xx, yy, pth_min}); break;}if(a[c * (xx - 1) + yy] == 1){//遇到A就说明可以直接返回这条路线了 ans = max(ans, pth_min);break;}}}while(!q.empty()){path t = q.top();q.pop();if(t.v <= ans)continue;//剪枝优化:当前这条路径已经废了,被阻挡的时间比我们已经求出来的还早 for(int i = 1; i <= 4; i++){xx = t.x;yy = t.y;pth_min = t.v;while(true){xx += dx[i];yy += dy[i];if(xx < 1 or yy < 1 or xx > r or yy > c) break;//边界条件判断if(a[c * (xx - 1) + yy] == 3)break;//剪枝 pth_min = min(pth_min, SMoke_TIme[c * (xx - 1) + yy]);//更新路径 if(a[c * (xx - 1) + yy] == 4){if(pth_min > vis[c * (xx - 1) + yy]){//如果是更好的子路 vis[c * (xx - 1) + yy] = pth_min;q.push(path{xx, yy, pth_min});}break;}if(a[c * (xx - 1) + yy] == 1){//合法路径直接返回 ans = max(pth_min, ans);break;}}}}
}main(void){input();BFS();solve_BFS();output();
}

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

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

相关文章

[Git] 放弃暂存区的修改

1 需求描述在使用 Git 进行版本控制时,有时我们会在暂存区(staging area)中暂存了一些修改,但后来发现这些修改是不需要的,想要放弃这些修改并恢复到上一次提交的状态。Git 提供了几种方法来实现这一操作。2 解决…

前端里面transform和transition 属性的区别

transform 和 transition 都是用于在 HTML 中控制元素的视觉效果和动画的 CSS 属性,但它们的作用和功能不同。下面详细解释这两个属性的区别: 1. transform 属性 transform 属性允许你对元素进行 2D 或 3D 转换(即对…

【MAC环境】安装多个 JDK - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

CF2064E Mycraft Sand Sort

Sol 首先 \(c\) 不能变,否则第一列就会改变。 然后注意到 \(i,j(i<j)\) 能交换当且仅当满足以下任意一条:\(\displaystyle\max_{k=i+1}^{j-1}a_k<\min(a_i,a_j)\) i+1=j那么考虑从小到大做,每次把小的数删除,…

使用eBPF技术保护FastAPI安全

本文详细介绍如何利用eBPF技术保护面向互联网的API安全,包括FastAPI、Flask、Django等框架。通过secimport工具实现Python代码的实时追踪、沙箱策略构建和运行时监控,有效防御远程代码执行等安全威胁。使用eBPF保护F…

项目案例作业2:对案例进行面向对象分析

学生管理系统面向对象分析报告 小组成员:李天瑞 202421336012 目录学生管理系统面向对象分析报告1. 案例中哪里体现出了封装性及其好处?封装性的体现封装性带来的好处2. 案例中的setter/getter模式与封装性什么是set…

20251010周五日记

20251010周五日记今天十点多回学校了,好不容易不下雨了。没想到国庆还真加了那么多天班= = 今日: 1.早上吃完早饭收拾东西慢慢悠悠回来了,打印朋辈表多亏师哥妙手回春。准备去开学代会,说来又要翘课了。 2.中午吃了…

k8s 主节点重启后 从节点 get 异常 - 教程

k8s 主节点重启后 从节点 get 异常 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "…

多维索引技术优化数据湖查询性能

本文介绍了一种通过多维索引技术优化数据湖查询性能的解决方案。该技术可直接集成到现有数据湖架构中,支持跨列复杂过滤,提升查询速度最高达6倍,同时降低70%计算成本,兼容主流计算引擎无需重构数据管道。Qbeast获7…

训练笔记:博弈杂题

[7-/7] A. 黎明\(1\sim n\) 排成一个环进行约瑟夫(隔一个删一个),求有多少个时刻,被删除的数的异或和为 \(0\)。 多测 \(10^5\) 组,\(n<10^{18}\)。hint:考虑把约瑟夫的过程分解为 \(\lceil\log n\rceil\) 个…

HTML5拖放API核心功能解析

好的,我们来详细解析一下 HTML5 拖放 API 的核心功能。 HTML5 拖放 API 允许用户在浏览器中抓取一个元素,并将其拖放到另一个位置。它原生支持在浏览器标签页、甚至不同浏览器、乃至桌面应用之间拖放,是现代 Web 应…

[USACO07NOV] Telephone Wire G

dp题,做法有点套路但是一开始没想到。 设 \(dp{_i}_j\) 表示第 \(i\) 位为 \(j\) 的最小花费。 然后直接往下转移就好了。点击查看代码 #include<bits/stdc++.h> #define fir first #define sec second #define…

springboot配置多个数据源

springboot配置多个数据源在我们的实际业务中可能会遇到;在一个项目里面读取多个数据库的数据来进行展示,spring对同时配置多个数据源是支持的。 使用到的框架:springboot+mybatis 方法:在配置文件中配置多个数据源…

Umi-OCR_文字识别工具 免安装使用教程(附下载安装包)!永久免费,开源离线OCR识别软件下载

软件介绍 在外面日常工作汇中,我们经常需要将图片、截图中的文字转换为可编辑文本。Umi-OCR应运而生——这是一款完全开源免费的离线OCR识别工具,无需联网即可本地完成高精度文字识别,保护你的数据隐私同时确保高效…

常量指针 和 指针常量

常量指针 和 指针常量Posted on 2025-10-10 19:52 steve.z 阅读(0) 评论(0) 收藏 举报如何牢记 “常量指针” 和 “指针常量” 的区别?🧩 一、先看词序规律:「前修后主」 在汉语里:前面的词修饰后面的词。比…

PyTorch 神经网络工具箱完全指南 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Apache POI:Java操控Office文档的利器

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

【汇总】OPPO r9m 分区名、分区功能

一、分区名、分区功能编号 分区名 英文说明 中文说明 备注、示例0preloaderfastboot 底层系统初始化程序分区 比 u-boot 更底层1pgpt2recovery系统救援工具、维护手机类似电脑PE系统3para4reserve15reserve26reserve37…

完整教程:LVDS系列30:Xilinx 7系 ADC LVDS接口参考设计(一)

完整教程:LVDS系列30:Xilinx 7系 ADC LVDS接口参考设计(一)2025-10-10 19:48 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !import…