【数独 1】不回溯,试试候选数法1ms高效解数独谜题-C++实现(上)

简介: 【数独 1】不回溯,试试候选数法1ms高效解数独谜题-C++实现(上)

一、什么是数独游戏


数独谜题可表示为一个9 * 9的大九宫格,它由9个小的九宫格(3 * 3格)组成。


每个谜题,81个单元格中的一部分格子会被赋予1 ~ 9中的一个数字,作为已知数字,剩余的单元格空着。数独谜题的解题就是要在空的格子中填入1 ~ 9中的数字,要求大九宫格的每一行、每一列、每一个小九宫格都包含九个不同的数字。


我们平常的数独游戏还有两个重要的特性。第一,每个数独游戏的解唯一。第二,可以通过推理来求解,即不需要列出所有可能的情况来一一行尝试。数独谜题解题的过程,就是通过已知的数字,不断推理来确定空白单元格中该填的数字的过程。


下面是一个推理过程的例子,以下图为例,数字4必须在第二行的某个单元格恰好出现一次,那么它应该在哪里呢?我们观察到,4不可能在这一行的前三个单元或后两个单元,因为4已经出现在这些单元所在小九宫格的其它单元中了;4也不能在这一行的第五个单元,因为它已经出现在这一列的其它单元中了。所以,我们可以得出结论,第二行的第6个单元中,一定是填4。



二、候选数法


每个单元格中都有1 ~ 9九个可能会填的数字,我们这些数字为该单元格的候选数。于是我们可以通过已有的数字,来删除其它单元格中的一些候选数,当某个单元格中的候选数只剩下一个时,这个单元格中的数字也就确定了。



三、设计程序


1、数独盘面和候选数在计算机中的表示

我们可以简单地用一个二维数组来表示一个数独的盘面,用一个三维数组来表示所有的候选数。

/*全局变量*/ 
//这里下标为0的位置不使用
int s[10][10]{};    //(行,列)数独的大九宫格盘面
bool p[10][10][10]{};   //(行,列,候选数字)


如: p[1][2][3] == 1 就表示第一行第二列的数字 3 候选状态,而 p[4][5][6] == 0 则表示第四行第五列填数字 6 的可能性已经被排除了。


2、算法过程

还记得数独要满足的三条规则吗?接下来就需要它们来帮助我们解数独谜题啦!

我们解一个数独谜题的过程如下:

第一步:通过给定的已知数字来删除一些候选数。对于一个已知的数字,我们删除包括处于同一行、列、小九宫的相同数字候选数,和这一单元格中的所有其它候选数。


第二步:寻找只剩下一个候选数的单元格,确定该单元格中应填入的数字。

第三步:通过第二步确定的数字,继续删除候选数。

然后重复第二步和第三步,直到得到最终的答案。若在某次循环中,填入数字和候选数都不再发生变化,则停止循环,解该数独谜题就失败咯。

相关文章
|
6月前
|
算法 C++
【C++】递归,搜索与回溯算法入门介绍和专题一讲解
【C++】递归,搜索与回溯算法入门介绍和专题一讲解
|
6月前
|
算法 机器人 C++
剑指offer(C++)-JZ13:机器人的运动范围(算法-回溯)
剑指offer(C++)-JZ13:机器人的运动范围(算法-回溯)
|
6月前
|
算法 C++
剑指offer(C++)-JZ12:矩阵中的路径(算法-回溯)
剑指offer(C++)-JZ12:矩阵中的路径(算法-回溯)
|
8月前
|
存储 算法 C++
【C/C++练习】经典的排列组合问题(回溯算法)——电话号码的字母组合
【C/C++练习】经典的排列组合问题(回溯算法)——电话号码的字母组合
79 0
|
定位技术 C++
C++实现俄罗斯方块(附代码)
C++实现俄罗斯方块(附代码)
C++实现俄罗斯方块(附代码)
|
机器学习/深度学习 C++
C++实现实现逆时针旋转矩阵
C++实现实现逆时针旋转矩阵
C++实现实现逆时针旋转矩阵
|
存储 C++
C++异常处理机制由浅入深, 以及函数调用汇编过程底层刨析. C++11智能指针底层模拟实现
C++异常处理机制由浅入深, 以及函数调用汇编过程底层刨析. C++11智能指针底层模拟实现
C++异常处理机制由浅入深, 以及函数调用汇编过程底层刨析. C++11智能指针底层模拟实现
|
存储 Linux C语言
生产者消费者模式保姆级教程 (阻塞队列解除耦合性) 一文帮你从C语言版本到C++ 版本, 从理论到实现 (一文足以)
生产者消费者模式保姆级教程 (阻塞队列解除耦合性) 一文帮你从C语言版本到C++ 版本, 从理论到实现 (一文足以)
生产者消费者模式保姆级教程 (阻塞队列解除耦合性) 一文帮你从C语言版本到C++ 版本, 从理论到实现 (一文足以)
|
设计模式 安全 定位技术
C++从面试常考实现特殊类到单例模式的实现
C++从面试常考实现特殊类到单例模式的实现
C++从面试常考实现特殊类到单例模式的实现
|
存储 Java 应用服务中间件
线程池设计, 从简单的我们平常设计线程池图解,到生活中的类似线程池的处理现实场景, 到简单的C++模拟nginx写的单链表组织工作队列的简单线程池实现 + nginx 部分源码刨析
线程池设计, 从简单的我们平常设计线程池图解,到生活中的类似线程池的处理现实场景, 到简单的C++模拟nginx写的单链表组织工作队列的简单线程池实现 + nginx 部分源码刨析
线程池设计, 从简单的我们平常设计线程池图解,到生活中的类似线程池的处理现实场景, 到简单的C++模拟nginx写的单链表组织工作队列的简单线程池实现 + nginx 部分源码刨析

热门文章

最新文章