回溯算法解数独问题
好久没写算法了,浅解个数独
本篇代码以伪代码为主,主要讲解解题思路
规则介绍:
首先数独的游戏规则,每个九宫格 每一行 每一列 每个数字只能出现一次(1-9)
开局时会生成一些不能改变数字的格子
按规则填满所有格子为过关
图下所示为前几天朋友卡关了的状态:
例如第二行第一列有一个固定的5,在它的九宫格里就不能再出现另一个5
第二行也不能再出现5,第一列也不能再出现5
回溯思路:
我需要一个方法能够解这道题,我称呼他为方法A
需要调用方法A就能自动解开这道题,但是按照回溯算法的解题思路,方法A中的核心代码只需要解开一个格子的值,然后在下一个格子的位置再调用方法A
就有了如下伪代码:
布尔 方法A(int x,int y){
//此处先省略解开当前格子的代码 传入的参数为格子的坐标
返回 方法A(x,y+1);
}
这样的话,只需要调用方法A(0,0) 在解开一个格子后,他会自动去解下一个坐标的格子
最终返回true表示解开了这道数独,否则没解开
但是一行只有9个格子,一共9列,所以添加如下代码自动换行(添加到方法顶端,先判断是否越界再运行核心代码):
if (x > 8) {
return true;
}
if (y > 8) {
return 方法A(x + 1, 0);
}
现在这个方法已经会自动寻找下一个格子了
但是如果这个格子里的数值是不能修改的,就应该跳过这个格子
我的方法是开始运行前就遍历一遍格子,如果值不为0(开始求解前就有值),就把这个格子标记为不可变
if(此格子的数值不可变){
return 方法A(x,y+1);
}
即使这里的y+1超过了下标上限,运行到下一个格子的时候也会自动修正
以上是部分回溯,当然后续还会根据情况修改
解题思路:
说明:我将开始解题前就有值的格子称为不可变格子,因为里面的值是固定的,不能改变
1、首先找到这个格子能填入的所有数值
以图中(0,0)为例,第0下标列中有5,4,1,7 第0下标行中有6,3,2 所在的九宫格中有5,1,7 所以这个格子只能填入8,9
提醒:
这个格子所在的九宫格里所有格子的特征:格子的行号除以3相等 格子的列号除以3相等
(左上角这个九宫格里的任何格子 行号除以3都为0 列号除以3都为0 而下面的九宫格行号除以3为1 列号除以3为0)
2、依次尝试能填的所有数字
先填入8,然后进行下一个格子,运行中如果发现下一个格子怎么填都不正确,说明前面的格子有存在错误的,则值清0,返回前面的格子,接着试下一个答案
例如:
(0,0)格子填入8,进入下一个格子 即调用了方法A(0,1) (0,1)格子中只能填入4,9 结果发现填哪个都不行,只能把自己重新赋值0 返回false
(0,0)接收到false 继续尝试下一个 尝试填入9 继续调用方法A(0,1)
以此类推,直到得到正确答案 如果所有值都试完了 都没有正确答案 则返回false
所以回溯部分的代码也需要一些修改
for(可填入的数字的集合){
格子(x,y)=可填入的数字
if(方法A(x,y+1)){
return true;
}
}
格子(x,y)=0
return false;
运行起来大概是这个样子
如果得到正确的解,会从最后一个格子返回 true
而前面的格子都是使用if(方法A(x,y+1))调用的后面的格子
接收到true后也会返回true 直到最初的方法A(0,0)也返回true
如果所有的方案都无法得到解 尝试完所有方案后 也会依次返回false
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
2021-11-12 回溯解八皇后问题