浅谈点灯游戏O(n^3)算法
点灯游戏(POJ1681/NKOJ P1987)
很显然的高斯消元,将的矩阵弄成一行,对其相邻格子的系数为1即可(表示点号格子,号格子是否受到影响),最后解方程即可。
NKOJ P8530 手机游戏 超级版
题意同NKOJ P1987,只不过数据范围从到了
一眼不可做,直接用P1987的做法时间复杂度为,不可行
考虑到只有取值,用优化常数,依然不可行
继续考虑暴力做法,假设我们已经确定了第一行点了哪些格子,我们可以推出行每行的状态(点或不点)
即对于第行的'#',通过的点击使其变成'.',这时候对于行无法再继续点击(不然维护的行不再合法),那么对于行的'#',只能通过点击行消掉,以此类推,直到得到最后一行无法被消除的状态。
说的简单一点就是对于第行,通过只点第行的方式让行全部为'.',当讨论完后, 到 全都是'.'
举个例子:
对于以下这个矩阵
.##
.#.
...
讨论点击第2行,修改第1行
点击(2,2)
..#
#.#
.#.
点击(2,3)
...
##.
.##
此时第1行已全被消除,考虑第2行
点击(3,1)
...
.#.
#.#
点击(3,2)
...
...
.#.
第2行也被消完,此时第3行还剩下一个无法被消除
显然,做完上述操作后,整个矩阵除了最后一行,其他一定是'.'
回到原题,题目是要求出给定矩阵使其全部熄灭的具体点击方案
我们发现在确定第一行状态后,我们可以推出其余行的状态(保证已经讨论过的行为熄灭)
那么从一个全熄灭状态转移到一个矩阵状态,等效于将这个矩阵全部熄灭,所以我们对于题目给出的矩阵跑一遍上述的过程,得到最后一行状态。
接着我们思考,这个东西有什么用?发现,如果一空矩阵点击了一些点后,最后一行状态(其余行全部为熄灭)等于了题目给定矩阵的最后一行状态,则这些点击的点被点后,可以将目标矩阵消完(也可以理解成
将空矩阵点成目标矩阵)
为了接下来的表述,我们把目标矩阵求的的最后一行设为
发现了以上特征后,我们开始考虑在全灭矩阵上如何使得点一些点让最后一行状态等于
因为已经发现第一行的状态就可以决定最后一行,那么我们考虑枚举第一行状态,,一样炸裂(好像炸的跟裂了)
于是怎么办呢?(我白银你问我?GG)
其实很简单 (毒瘤),我们慢慢来,先讨论只点1个的情况,很简单对吧,直接点,然后往下讨论就行了,那么如果点2个呢,也很简单,可以看成先点1个,再点1个,对于重复了的部分就相当于没点,这个操作是不是有点像异或?那么对于点个点,最后一行的状态就是把这个点单独的状态异或起来,就完了,是不是很简单。
于是,我们可以预处理出每个位置点击后最后一行的状态,发现时间复杂度有点过分,但只有取值,bitset优化即可
接着就是如何找出选出第1排的那些点,可以使得异或之和等于
发现单独列之间的影响是独立的,即只会受到的影响,与其他列无关,可以看成方程组。
考虑高斯消元
把状态数组竖着摆放成为方程矩阵,的值表示第1行号点是否需要点击,矩阵的值即为系数
接着解一个异或方程组就完事了
时间复杂度,完全跑得过
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现