Hatsune Miku Logic Paint S

Hatsune Miku Logic Paint S

Not enough ratings
题解:使用正反排除法解初音未来填色问题
By Jelly
该指南使用Python编写算法,以求解初音未来填色问题。
   
Award
Favorite
Favorited
Unfavorite
题解
基本思路
1. 横向搜索,找出每一行的所有可能解。

2. 把每一行的所有可能解取按位与,得到确定填色的方块(正向排除);每个解取非,再按位与,结果再取非,得到确定不填色的方块(反向排除)。

3. 竖向搜索,找出在已有确定填色方块和确定不填色方块的基础上,每一列的所有可能解。

4. 把每一列的所有可能解取按位与,得到确定填色的方块;每个解取非,再按位与,结果再取非,得到确定不填色的方块。

5. 重复1-4步,直到棋盘收敛。如果收敛结果符合游戏要求,则得到解;否则可能无解或存在多解。

如何寻找一行的所有解?
采用递归方法。比如某行左侧的数字为“4, 3, 1”,第一个数字n必须满足以下规则:

(1) 设窗口长度为n,窗口要能在棋盘中放得下。

(2) 窗口左侧区域必须是边界或者连续空格。

(3) 窗口之中方块不能指定为不该涂色状态。

(4) 窗口右侧区域必须是边界或者有一个空格。

筛选出所有符合条件的窗口,把窗口内的格子都填色。从这一行所有格子中删去窗口、窗口左侧所有空格以及窗口右侧的一个空格(如有),并删去第一个数字,把剩下的格子和数字拿去递归。最后把窗口内格子和递归结果拼起来,得到解。

代码
Gist链接:https://gist.github.com/JellyBlack/00f60ca4ae34809ea7d1a934ec69cc02

求解示例
图为关卡Lv3-001的求解结果。


局限性
该算法局限于题目有唯一解的情况,如果题目无唯一解,那么棋盘收敛时始终存在不确定的方块,无法返回结果。对于有多解的情况,可以使用回溯法或者广度优先搜索,对剩余解进一步剪枝,从而找出最终解。该部分留作习题,请读者自行完成。
1 Comments
qkndlxz 25 Jan @ 4:13am 
解题过程中待检查的行和列可以用容器单独存放,例如 [C1,C2,L3];当某一列(例如C1)有新的填色方块 (例 C1L2) 和不填色方块 (例 C1L3) 确定后,只需检查对应的行 (例 L2, L3) 即可,更新容器([C1, C2, L2, L3]);对行同理。退出条件不再是棋盘无变化,而是容器为空。
贴一份自己写的 https://gist.github.com/U-73A5/9e1a4d4452ca5dff0d9b37651f86ca04