关于回溯法
参考这里
计算机解数独的一种思路
计算机有着高速运算能力,因此不用像人解数独一样讲究技巧(每次随机瞄一个位置,能用排除法得到唯一结果的直填,或者有配对数一定填在特定的相同数量格子里时其他格子可直接排除这些数,等)。
计算机可以在每个空格子里试填1-9的数,填好之后往后继续填,填到填不了的时候,表明之前填的是有错误的,需要回溯。
比如说,下面就是leetcode该题给出的示例九宫格(侵删)
回溯条件
首先我们需要一个回溯用的函数,即判断当前填进去的数是否合法(不合法的填进去直接就错了,都不用往后跟)
举个例子(借一下leetcode题解的那个图),这里蓝色是填上去的数(在判定条件中返回了true),白底色的数是题目原有的。在填到第1行第9列这个格子的时候,第一行只剩6这个选项,而6已经在同一列上(以及同一个9宫内)存在,因此这个格子实际上从1-9都是不合法数字了,因此需要回溯。比起暴力穷举法,在这里回溯可以省掉大概9^72次尝试。
那么分析以下数字填进去在什么情况下是非法的。非法数字规则的算法在leetcode上也有题目,具体就是,这个数字填进去后,在同一行不能有重复数字,在同一列不能有重复数字,在同一个九宫内不能有重复数字。由于一个格子内填数对全局的影响仅限于该格所在列、行与九宫,因此分别给予判断条件,即可实现合法性判断。其他无关元素无需判断。
每一项判断条件的判断方法为:这9个格子里是否已经存在待填数字。用一个重复9次的循环即可。判断九宫的比较复杂,需要定位到所在的九宫,涉及到九宫的编号、for循环范围限制的精确计算问题,可用草稿纸演示一遍思路。
bool legalInput(int arr[][9], int in_x, int in_y, int in_val){
//判断输入/填数的合法性
//参数:arr 待填九宫格、(in_x,in_y)待填坐标,in_val 待填数字
//return true返回可填,false表示不合法
if(in_x < 0 || in_x >= 9 || in_y < 0 || in_y >= 9 || in_val <= 0 || in_val > 9)return false; //无效输入
int i,j;
for(i = 0;i < 9; i++