[BalticOI 2010] Mines 题解

news/2024/4/26 20:39:33/文章来源:https://www.cnblogs.com/LaoMang-no-blog/p/16777418.html

你谷 link

loj link

提供一种时间复杂度正确的高妙做法。

首先题目有一条隐藏条件是保证 \(n\not\equiv2\pmod3\)\(m\not\equiv2\pmod3\),需要通过观察数据得到。

我们钦定 \(n\not\equiv2\pmod3\),如果不满足则沿主对角线翻转使其满足。

接下来我们令 \(a_{i,j}\) 表示原给定数字表格上第 \(i\) 行第 \(j\) 列的值,\((i,j)\) 表示第 \(i\) 行第 \(j\) 列是否有雷。

首先考虑一种特殊情况,\(a_{x,y}+a_{x+1,y+1}-a_{x,y+1}-a_{x+1,y}=(x-1,y-1)+(x+2,y+2)-(x-1,y+2)-(x+2,y-1)\),即对于一个 \(2\times2\) 的方格,若我们已知其三个角,我们可以直接求得另外一个角。

思路非常巧妙,首先确定第 \(3\) 行。

利用前面的特殊情况可以递推求出所有 \((3,3k)\),接下来求别的,需要对 \(m\) 分类讨论。

\(m\not\equiv2\pmod3\),我们将整个图水平翻转,再做一遍,则第三行任意三个相邻的位置只有一个未知,可以直接求。

\(m\equiv2\pmod3\),此时我们将第三行中所有未知的位置取出来排成一列,任意两个相邻位置的和都是已知的,若有 \(2\)\(0\),两个就都确定了,若全都是 \(1\),则我们发现任意两个相邻的位置里只要有一个雷就好了,所以直接任意确定一组没有关系。

以此类推,当第 \(3\) 行已知后,将第 \(3\) 行对全图的影响消去,第 \(6\) 行的情况就等价于原来的第三行,以此类推求得所有第 \(3k\) 行。

因为保证了 \(n\not\equiv2\pmod3\),竖直翻转后重新求一遍则所有未知行两两之间隔了两行,不会互相影响,即可以独立求。

求一个 \(1\times m\) 的矩阵非常简单,直接和上面求第 \(3\) 行类似做就好了。

最佳实现时间复杂度是 \(\mathcal O\left(nm\right)\)

实现上因为全图翻转是 \(\mathcal O\left(nm\right)\) 的,所以上面讲到做第 \(3\) 行时翻转,实际上不能做一次翻一次,时间复杂度会退化,因为上面讲到特殊情况中有影响的实际上只有四个顶点,那么只要全部一起做就可以只反翻转一次。

细节较多,一个比较好的实现是每确定一个雷就将它在图中的影响消去,写起来会相对简单。

c++ 代码
#include<bits/stdc++.h>using namespace std;#define Reimu inline void // 灵梦赛高
#define Marisa inline int // 魔理沙赛高
#define Sanae inline bool // 早苗赛高
#define Reisen inline LL  // 铃仙赛高typedef long long LL;
typedef unsigned long long ULL;
typedef __int128 Suika;inline ostream &operator<<(ostream &cout, Suika x) {static const LL LIM = 1e18;return x < LIM ? cout << LL(x) : cout << LL(x / LIM) << setw(18) << setfill('0') << LL(x % LIM);
}typedef pair<int, int> Pii;
typedef tuple<int, int, int> Tiii;
#define fi first
#define se second#define all(vec) vec.begin(), vec.end()
#define TY(type) const type&template<typename Ty>
Reimu clear(Ty &x) { Ty().swap(x); }const int N = 610;int n, m, revFlg;
int fr[3], fc[3];
char s[N];
int a[N][N], b[N][N];Reimu swp(int i1, int j1, int i2, int j2) { swap(a[i1][j1], a[i2][j2]); swap(b[i1][j1], b[i2][j2]); }Reimu reverse1() {int mx = max(n, m);swap(n, m);for (int i = 1; i <= mx; ++i) {for (int j = 1; j < i; ++j) {swp(i, j, j, i);}}
}
Reimu reverse2() {for (int i = 1; i <= n >> 1; ++i) {for (int j = 1; j <= m; ++j) {swp(i, j, n - i + 1, j);}}
}
Reimu reverse3() {for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m >> 1; ++j) {swp(i, j, i, m - j + 1);}}
}#define safe(i, j) ((i) > 0 && (i) <= n && (j) > 0 && (j) <= m)#define set set_
Reimu set(int x, int y, int o) {if (!o) return;b[x][y] = 1;for (int i: {x - 1, x, x + 1}) for (int j: {y - 1, y, y + 1}) if (safe(i, j)) --a[i][j];
}Reimu solve1() {auto calc1 = [&](int i) { for (int j = 3; j <= m; j += 3) set(i, j, a[i - 2][j - 2] + a[i - 1][j - 1] - a[i - 2][j - 1] - a[i - 1][j - 2]); };for (int i = 3; i <= n; i += 3) calc1(i);if (fc[0]) {reverse3();for (int i = 3; i <= n; i += 3) calc1(i);reverse3();for (int i = 3; i <= n; i += 3) {for (int j = 1; j <= m; ++j) if (!fc[j % 3]) {set(i, j, a[i - 1][j] - a[i - 2][j]);}}return;}auto calc2 = [&](int i) {for (int j = 0; j <= m; j += 3) {if (j) do {int t = a[i - 1][j] - a[i - 2][j];if (t & 1) continue;t >>= 1; set(i, j - 1, t); set(i, j + 1, t);for (int k = j - 2; k > 0; --k) if (k % 3) set(i, k, a[i - 1][k + 1] - a[i - 2][k + 1]);for (int k = j + 2; k <= m; ++k) if (k % 3) set(i, k, a[i - 1][k - 1] - a[i - 2][k - 1]);return;} while (false);int t = a[i - 1][j + 1] - a[i - 2][j + 1];if (t & 1) continue;t >>= 1; set(i, j + 1, t); set(i, j + 2, t);for (int k = j - 1; k > 0; --k) if (k % 3) set(i, k, a[i - 1][k + 1] - a[i - 2][k + 1]);for (int k = j + 4; k <= m; ++k) if (k % 3) set(i, k, a[i - 1][k - 1] - a[i - 2][k - 1]);return;}for (int j = 0; j <= m; j += 3) set(i, j + 1, 1);};for (int i = 3; i <= n; i += 3) calc2(i);
}
Reimu solve2() {auto calc1 = [&](int i) { for (int j = 3; j <= m; j += 3) set(i, j, a[i][j - 1] - a[i][j - 2]); };for (int i = 1; i <= n; ++i) if (!fr[i % 3]) calc1(i);if (fc[0]) {reverse3();for (int i = 1; i <= n; ++i) if (!fr[i % 3]) calc1(i);reverse3();for (int i = 1; i <= n; ++i) if (!fr[i % 3]) {for (int j = 1; j <= m; ++j) if (!fc[j % 3]) {set(i, j, a[i][j]);}}return;}auto calc2 = [&](int i) {for (int j = 0; j <= m; j += 3) {if (j) do {int t = a[i][j];if (t & 1) continue;t >>= 1; set(i, j - 1, t); set(i, j + 1, t);for (int k = j - 2; k > 0; --k) if (k % 3) set(i, k, a[i][k + 1]);for (int k = j + 2; k <= m; ++k) if (k % 3) set(i, k, a[i][k - 1]);return;} while (false);int t = a[i][j + 1];if (t & 1) continue;t >>= 1; set(i, j + 1, t); set(i, j + 2, t);for (int k = j - 1; k > 0; --k) if (k % 3) set(i, k, a[i][k + 1]);for (int k = j + 4; k <= m; ++k) if (k % 3) set(i, k, a[i][k - 1]);return;}for (int j = 0; j <= m; j += 3) set(i, j + 1, 1);};for (int i = 1; i <= n; ++i) if (!fr[i % 3]) calc2(i);
}
Reimu solve() {solve1(); reverse2();solve1(); reverse2();solve2();
}int main() {ios::sync_with_stdio(false); cin.tie(nullptr);cin >> n >> m;for (int i = 1; i <= n; ++i) {cin >> s + 1;for (int j = 1; j <= m; ++j) a[i][j] = s[j] & 15;}if (n % 3 == 2) revFlg = 1, reverse1();fr[0] = fc[0] = 1; fr[(n + 1) % 3] ^= 1; fc[(m + 1) % 3] ^= 1;solve();if (revFlg) reverse1();for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m; ++j) cout << ".X"[b[i][j]];cout << '\n';}return 0;
}

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

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

相关文章

ORACLE新增数据库(用户),使用navicate

oracle新增数据库并不像mysql直接指令就行&#xff0c;百度一圈都是用Oracle Database Configuration Assistant的&#xff0c;其实navicate就直接可以新建&#xff0c;以下是新建方法&#xff1a; 1.连接数据库 2.新建表空间 点击navicate上方工具栏中"其它"&…

何为功能平价?特斯拉「抛弃」多传感融合,背后有哪些门道

技术与成本&#xff0c;永远是博弈的两方。 当大部分车企都在寻求通过增加更多、更高性能的传感器&#xff08;也就是通常所说的多传感融合技术&#xff09;来强化智能驾驶功能可靠性和拓展性的大背景下&#xff0c;特斯拉依然我行我素&#xff0c;继续沿着纯视觉感知的路线前…

盘点一个Python列表(元素多样)处理的实战题目(使用正则表达式也可以实现)

大家好,我是Python进阶者。 一、前言 前几天在Python白银交流群【凡人不烦人】问了一个Python列表处理的问题,提问截图如下:下面是他的部分数据: lst = [(问答题)(2) 假设镀锌钢管, http://admintk.sc.zzstep.com/UpLoadImage/2019-10-10/a84f340e-6c67-42b1-8eae-3dc14281…

队列的操作实验(数据结构)

队列的操作实验&#xff08;数据结构&#xff09; 一、实验目的 1&#xff0e;掌握队列存储结构的表示和实现方法。 2&#xff0e;掌握队列的入队和出队等基本操作的算法实现。 3&#xff0e;了解队列在解决实际问题中的简单应用。 二、实验内容 1&#xff0e;建立顺序循环队列…

【LeetCode】【二叉搜索树迭代器】

173. 二叉搜索树迭代器 实现一个二叉搜索树迭代器类BSTIterator &#xff0c;表示一个按中序遍历二叉搜索树&#xff08;BST&#xff09;的迭代器&#xff1a; BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会作为构造函数的一部分给出。指…

【优化充电】基于matlab粒子群算法电动汽车充电动态优化策略【含Matlab源码 2163期】

一、粒子群算法电动汽车充电优化 1 电动汽车充电负荷估算 电动汽车的充电负荷主要与电动汽车起始充电时刻和充电时长相关,而起始充电时刻是由电动汽车用户的到家时间决定的,充电时长主要与电动汽车的行驶里程和充电倍率相关。 目前电动汽车还没有大规模运营, 只能通过统计燃油…

ASP.NET Core微服务(六)——【.Net Core操作redis】StackExchange.Redis

ASP.NET Core微服务(六)——【.Net Core操作redis】StackExchange.Redis 目录 ASP.NET Core微服务(六)——【.Net Core操作redis】StackExchange.Redis 项目创建 StackExchange.Redis操作示例 引包【using StackExchange.Redis;】 ConnectionMultiplexer RedisDBHelper …

Git学习总结

目录&#xff1a; &#xff08;1&#xff09;版本控制 &#xff08;2&#xff09;Git和SVN的区别 &#xff08;3&#xff09;Git历史 &#xff08;4&#xff09;安装Git及环境配置 &#xff08;5&#xff09;常用的Linux命令 &#xff08;6&#xff09;Git的必要配置 &a…

PMO和PM如何实现从战略解码到项目执行的端到端闭环?

一、PMO的使命与职责 PMO的使命是提升端到端组织效能&#xff0c;赋能于精细化管理&#xff0c;成为企业的加速器&#xff0c;保障战略项目的交付。 那么PMO要保障战略的交付&#xff0c;核心职责有哪些呢&#xff1f; 二、组织为什么需要端到端项目管理&#xff1f; 核心价…

【ZooKeeper】ZooKeeper 应用场景

ZooKeeper 应用场景发布订阅命名服务集群管理分布式锁分布式队列管理负载均衡配置管理ZooKeeper&#xff1a;分布式协调服务&#xff0c;仲裁机构。基于ZNode数据模型和Watcher监听机制可以解决很多问题&#xff0c;比如分布式锁问题。 应用场景如下&#xff1a; 1、发布/订阅 …

servlet基础知识

早期的Web应用主要用于浏览新闻等静态页面&#xff0c;HTTP服务器&#xff08;比如 Apache、Nginx&#xff09;向浏览器返回静态 HTML&#xff0c;浏览器负责解析HTML&#xff0c;将结果呈现给用户。随着互联网的发展&#xff0c;还希望进行一些交互操作来获取动态结果&#xf…

Python Turtle绘图基础(一)——Turtle简介、绘图窗体与绘图区域

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是Python Turtle绘图基础&#xff0c;包括Turtle简介、绘图窗体与绘图区域。 一、Turtle库简单介绍 Turtle库时Python语言的标准库&#xff08;所谓标准库&#xff0c;就是在安装Python时自带的库&#xff0c;与之…

【经典面试题-LeetCode69/剑指 Offer II 072:x 的平方根 (Python3实现)】

x 的平方根一、题目描述1.题目内容2.样例二、解决方案1.基本代码&#xff08;成功提交&#xff09;2.略微拓展一、题目描述 这是一道经典的面试题&#xff0c;需要我们在不使用任何内置函数的前提下&#xff0c;手动实现求指定整数的算术平方根。 1.题目内容 给你一个非负整数…

Android开发——底部导航栏设计

底部导航栏设计1.依赖配置2.tabbar的UI实现3.tabbar的逻辑绑定4.tabbar的滑动与点击联动其实,常见的Android和微信小程序一样&#xff0c;通常最下面一排需要有一排导航栏&#xff0c;可以通过点击导航栏图标和滑动实现页面跳转&#xff0c;具体实现使用的是Android的 ViewPage…

在MUI框架中对于事件绑定与取消和监听的触发自定义的深入运用与实战

事件绑定 除了使用addEventListener&#xff08;&#xff09;方法侦听特定元素上的事件外&#xff0c;还可以使用。on&#xff08;&#xff09;方法实现批元素的事件绑定。 event Type: String 需监听的事件名称&#xff0c;例如&#xff1a;‘tap’ selector Type: String 选择…

MySQL集群搭建——主从同步(一主二从)

一、安装MySQL数据库 Centos7安装MySQL5.7 目前准备了三台服务器作为主从配置数据库 #主 192.168.159.100:3306 #从 192.168.159.101:3306 #从 192.168.159.102:3306二、修改主数据库配置文件 vim /etc/my.cnf #在mysqld模块中添加如下配置信息 #开启二进制日志 log-binmast…

Win10家庭版利用Hyper-V虚拟机安装Kali Linux

目录 安装Hyper-V 批处理安装 重启电脑 下载Kali镜像 Kali官网下载 Hyper-V虚拟机 创建虚拟机 启动虚拟机 安装Kali 安装前配置 磁盘分区 系统安装 登录系统 近期学习网络安全的相关内容&#xff0c;需要用到很多的安全工具。偶然得知Kali Linux就是专门为网络安…

SD-WAN是面向分支机构的新兴、不断发展的解决方案

在过去的二十年里&#xff0c;人们的工作方式发生了很大变化。共享办公空间、移动性和云现在很常见。业务分散&#xff0c;分支机构得到授权。 当然&#xff0c;这个新功能是一件好事。但是&#xff0c;与此同时&#xff0c;它提出了一个巨大的挑战&#xff1a;多协议标签交换(…

【潮流计算】基于matlab粒子群算法优化电力系统潮流计算【含Matlab源码 2157期】

一、粒子群算法简介 1 标准粒子群优化(PSO)算法 PSO算法根据对环境的适应度将群体中的个体移动到好的区域,将每个个体看作是D维搜索空间中的一个粒子,根据粒子本身的飞行经验和群体中其他同伴的飞行经验调整下一步飞行方向,从而搜索到最好的空间位置解。设第i个粒子的位置表示…

什么是 IoT App SDK?

目录 为什么要开发 IoT App&#xff1f; IoT App SDK 的优势 IoT App SDK 分类 智能生活 App SDK 商用照明 App SDK 智慧社区 App SDK 智慧居住 App SDK 行业 App SDK 其他概念 IoT 设备 通信过程 IoT 云平台 智能面板 名词解释 涂鸦 IoT App SDK 是专为物联网移…