2024牛客暑期多校训练营1 I.Mirror Maze(题解)

news/2024/11/15 21:05:58/文章来源:https://www.cnblogs.com/TJUHuangTao/p/18306749

题意

给一个 \(n \times m\) 的二维char数组,由4种镜子组成,'\', '/', '-', '|',镜面反射规则就是根据光线的方向和镜面的角度符合直觉的反射,然后有多组询问 \(q \leq 10^6\),每次给定起始位置和光线方向,求该光会经过多少面不同的镜子的反射。

思路

首先根据数据范围,发现肯定需要预处理答案,然后每次 \(O(1)\) 回答,所以考虑如何进行预处理,首先显然预处理是开一个 \(ans[n][m][4]\) 的数组,把每个位置的4种方向对应答案都存起来。(注意:这里的 \(ans[i][j][k]\) 表示的是方向为 \(k\) 的光线正要射向 \(ch[i][j]\) 的镜子时,总的会反射过的镜子数。而题目询问时起点的镜子不算,所以询问时要先根据方向移动一格,才对应上前面设置的状态的含义)

然后需要一些性质,一束光在这个矩阵里要么是陷入死循环,要么就一定会射出去越界消失。所以需要分别处理这两种情况。

还有最重要的一个性质就是,因为光路可逆, 所以每个状态(即上面的总共 4nm种状态),一定只对应一条光路,也就是光路之间一定是没有重合的。这就启示了,可以直接爆搜,爆搜出来的状态不会有重复的。

然后就到了如何把环与链单独抽出来的问题,这个也是本题的难点(题解里只是讲了思路,具体如何抽,感觉也是非常考察代码能力)。赛后看了别人的代码,发现了巧妙的抽法。

还是由于前面的性质,对于一个链,最终肯定是射向出界,所以我们可以反过来,从四个边界往里射入光线,这些状态一定是可以作为链的起点的,然后根据题意爆搜,直到再次出界为止。把过程中经历的所有状态全部存起来(可以用vector<tuple<int, int, int>>储存),这些状态就是链上的状态,然后倒叙遍历状态,维护每个状态的前缀会反射过的镜子(实现上,我先用一个函数表示一个状态是否会反射到那个位置的镜子,再用一个set把反射到的镜子的位置存起来),然后就处理好了链。

接下来考虑处理环,因为前面已经把所有可能的链都处理好,所以直接暴力 for 循环遍历总的 4nm种状态,如果有状态未访问过,说明这个状态一定在环上,直接从它开始再暴力dfs,直到又到达一个已经访问过的状态,说明环走完了,对这些状态全部反射过的镜子用set存一下,然后set的大小就是这个环上所有状态的答案。

最后的询问,先根据方向偏移一下,然后直接输出预处理的答案即可。代码细节如下:

点击查看代码
#include <bits/stdc++.h>
#define pii pair<int, int>
#define tii tuple<int, int, int>
#define all(a) a.begin(), a.end()
using namespace std;
const int maxn = 1e3 + 10;
char ch[maxn][maxn];
int n, m, ans[maxn][maxn][4];
int vis[maxn][maxn][4];
vector<tii> vec;
bool istan(int x, int y, int dir) {  // 标记某个状态是否有经过镜子的反射char tem = ch[x][y];if (tem == '/' || tem == '\\')return 1;if (tem == '-' && (dir == 0 || dir == 1))return 1;if (tem == '|' && (dir == 2 || dir == 3))return 1;return 0;
}
void dfs(int x, int y, int dir) {// 根据题意模拟反射过程,越界或者访问过退出if (x < 1 || x > n || y < 1 || y > m)  // 链的退出条件return;if (vis[x][y][dir])  // 环的退出条件return;vec.push_back(tii(x, y, dir));vis[x][y][dir] = 1;if (ch[x][y] == '/') {if (dir == 0) {dfs(x, y + 1, 3);} else if (dir == 1) {dfs(x, y - 1, 2);} else if (dir == 2) {dfs(x + 1, y, 1);} else {dfs(x - 1, y, 0);}} else if (ch[x][y] == '\\') {if (dir == 0) {dfs(x, y - 1, 2);} else if (dir == 1) {dfs(x, y + 1, 3);} else if (dir == 2) {dfs(x - 1, y, 0);} else {dfs(x + 1, y, 1);}} else if (ch[x][y] == '-') {if (dir == 0) {dfs(x + 1, y, 1);} else if (dir == 1) {dfs(x - 1, y, 0);} else if (dir == 2) {dfs(x, y - 1, 2);} elsedfs(x, y + 1, 3);} else if (ch[x][y] == '|') {if (dir == 0)dfs(x - 1, y, 0);else if (dir == 1)dfs(x + 1, y, 1);else if (dir == 2) {dfs(x, y + 1, 3);} else {dfs(x, y - 1, 2);}}
}
void solve1(int x, int y, int dir) {// 处理链vec.clear();dfs(x, y, dir);reverse(all(vec));  // 倒叙遍历状态更新答案set<pii> s;for (auto [a, b, c] : vec) {if (istan(a, b, c))s.insert(pii(a, b));ans[a][b][c] = s.size();}
}
void solve2(int x, int y, int dir) {// 处理环vec.clear();dfs(x, y, dir);set<pii> s;for (auto [a, b, c] : vec) {if (istan(a, b, c))s.insert(pii(a, b));}for (auto [a, b, c] : vec)ans[a][b][c] = s.size();  // 环上的答案都一样
}
signed main() {ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);cin >> n >> m;for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)cin >> ch[i][j];// 从边界射入的光线一定是链for (int i = 1; i <= n; i++)solve1(i, 1, 3), solve1(i, m, 2);for (int j = 1; j <= m; j++)solve1(1, j, 1), solve1(n, j, 0);// 还未访问的状态,一定是环上的状态for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)for (int k = 0; k < 4; k++)if (!vis[i][j][k]) {solve2(i, j, k);}int q;cin >> q;map<string, int> mp;mp["above"] = 0;mp["below"] = 1;mp["left"] = 2;mp["right"] = 3;while (q--) {int x, y;string str;cin >> x >> y >> str;// 先根据方向偏移一格int tem = mp[str];if (tem == 0)x--;else if (tem == 1)x++;else if (tem == 2)y--;elsey++;cout << ans[x][y][tem] << "\n";}return 0;
}

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

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

相关文章

基于M3u8的视频加密及播放

准备工作安装ffmpeg mac安装 brew install ffmpeg加密准备生成enc.keyopenssl rand 16 > enc.key ( 生成一个enc.key文件 )生成 ivopenssl rand -hex 16 ( 生成一段字符串,记下来)新建一个文件 enc.keyinfo 内容格式如下:Key URI # enc.key的路径,使用http形式 Pa…

zabbix6.4分离部署笔记

Zabbix 6.4 分离部署实施过程 一、环境准备 三台服务器### 操作系统:RED HAT ENTERPRISE LINUX 8.3 数据库:MYSQL8.0 ip地址以及用途:Zabbix 前端,8C 16G 16G系统盘100G:10.0.13.71 1371zabbixwebZabbix服务后端,8C 16G 100G:10.0.13.63 1363zabbixserverZabbix数据库MySql…

极大值抑制 nms 代码详解

NMS: 非极大值抑制(Non-Maximum Suppression), 功能:从大量的预测结果中筛选出得分最高的结果。 思路:NMS的主要思路是通过计算目标框之间的重叠度(即IOU,交并比)来剔除非最佳结果。NMS介绍 一张图片经过模型的前向推理之后,会输出非常多的检测结果,如下图Prediction所…

终端日志查看工具

tailspin 安装: # macOS brew install tailspin# Cargo cargo install tailspin使用: tspin <file>lnav 安装: # macOS brew install lnav# Ubuntu sudo snap install lnav使用: lnav <file>

Cisco ACI Simulator 6.0(6c)M - ACI 模拟器

Cisco Nexus 9000 Series Switches, NX-OS Standalone 10.4(3)F and ACI Mode 16.0(6c)MCisco ACI Simulator 6.0(6c)M - ACI 模拟器 Application Centric Infrastructure (ACI) Simulator Software 请访问原文链接:https://sysin.org/blog/cisco-acisim-6/,查看最新版。原创…

新文章:“Java 中的 finally 代码块不执行的情况”

新文章:“Java 中的 finally 代码块不执行的情况” - https://www.emanjusaka.top/2024/07/java-finally-non-execution 先抛出一个问题:Java 中的 finally 代码块一定会被执行吗?这是一个比较常见的面试题,在我们的印象中好像 finally 的代码块是一定会被执行的。但真实的…

SublimeText 4.4169 汉化版

SublimeText是编辑器中的一款神级IDE,非常有名,虽然比较轻量,但是呢软件拓展性非常强大,适用于多种编程语言,当然,当一个编辑器,也是非常不错的。 SublimeText支持但不限于 C, C++, C#, CSS, D, Erlang, HTML, Groovy, Haskell, HTML, Java, JavaScript, LaTeX, Lisp, L…

表格集算表高性能原理:揭秘纯前端百万行数据秒级响应的魔法

最新技术资源(建议收藏) https://www.grapecity.com.cn/resources/集算表 (Table Sheet)是一个具备高性能渲染、数据绑定功能、公式计算能力的数据表格,通过全新构建的关系型数据管理器结合结构化公式,在高性能表格的基础上提供排序、筛选、样式、行列冻结、自动更新、单…

eclipse免安装版64位 2018版本

前言Eclipse 是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse 附带了一个标准的插件集,包括Java开发工具(Java Development Kit,JDK)。虽然大多数用户很乐于将 Eclipse 当作 Jav…

Iceberg v2表写入和微批治理冲突,如何保证治理准确性

一、背景 微批治理任务分多个job治理一张表,还有一个Flink程序每5分钟一次写入iceberg表,如治理任务划分了20个job治理一张表,在治理期间存在新的数据更新,如何保证治理准确性 二、猜想待验证 1、治理和写入时快照和文件变化snapshot_id manifest_file 备注

Fastjson的payload收集

收集了网络上的多种payload,方便进行fuzz测试What 无第三方依赖 收集了网络上的多种payload,方便进行fuzz测试 提供了自动替换payload的功能,一次性为所有payload插入rmi地址/dnslog Help --list:以清单的形式打印,方便作为字典进行fuzz --address:服务器地址(无需rmi:/…

DBeaver安装教程(开发人员和数据库管理员通用数据库管理工具)

前言 DBeaver 是一个通用的数据库管理工具和 SQL 客户端,支持 MySQL, PostgreSQL, Oracle, DB2, MSSQL, Sybase, Mimer, HSQLDB, Derby, 以及其他兼容 JDBC 的数据库。DBeaver 提供一个图形界面用来查看数据库结构、执行SQL查询和脚本,浏览和导出数据,处理BLOB/CLOB 数据,修…