DFS算法解决数独问题
一,情景描述
一天晚自习,看到女朋友在旁边玩数独,便想着不如用个算法帮助她快速通关。毕竟,我想以后能成为一个AI算法工程师,所以现在不管是什么算法,多写点总归是有好处的。
对于这个程序的功能,我希望它能够从文件夹里读取棋盘,然后运行之后输出完整的棋盘。这样对于不同的棋盘,只要更改一下文件路径,就能输出结果。其实,我想着利用计算机视觉就可以直接输入图片,然后电脑自己处理自己输出。但是奈何大二的自己还对计算机视觉一无所知,就只能手动输入到文本文件中了。
二,最初思路
最开始,我的思路是1,先将棋盘遍历一遍,获取所有空格位置(横纵坐标),然后将他们放在一个数组里面。2,由于每个空格位置所填的内容是1~9之间的数字,所以对每个空格,从1开始,按照行列和所属九宫格进行三次筛选,删去不可能的数值。3,经过前两步的筛选,就可以锁定每个空格能够填的几个数字。然后利用蛮力法进行一种一种的尝试。
为了实现这个思路,首先定义数据结构如下:
struct point{
int x,y; //表示棋盘的每一格所在行,所在列
strign maynum="123456789"; //初始设置空格可能所取的值
int index; //用来指示具体空格的值
}
如上,设置了这样一个复杂的结构,并定义了一个一维数组 point zero[n];
zero[m] 表示第m+1个空格。则zero[m].x和zero[m].y就能分别表示这个空格在棋盘的第几行第几列,zero[m].string[zero[m].index]; 就能表示这个空格的值。于是,照着这个思路,我完成了最初思路的前面两步,等到最后一步准备蛮力法的时候,发现不知道该如何遍历了。要是硬生生继续写下去,那怕不是要写出个m层循环出来,瞬间失去方向。最终,我还是选择来到优快云上观摩各位大佬的文章。才学得了DFS算法的思路(上学期学习数据结构,学到图的遍历时,怎么没想到这DFS如今还能派上用场。)
三,最终思路
最终思路为:先从第一个空格开始,对其调用dfs算法为其赋上一个可能值,如果合法,则对下一个空格调用dfs算法。如果有一个空格所有可能值都不合法,则跳出递归函数返回上一个空格,对其赋值下一个可能值,再重复往后进行,知道能够输出全部完整的棋盘为止。完整代码如下:
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
int dataa[10][10];
//建立二维数组用来存储数独棋盘
void Create()
{
ifstream infile;
infile.open("D:\\Visual Studio 2017\\代码项目文件夹\\Project1\\数独3.txt", ios::in);
if (!infile.is_open())
{
cout << "读取文件失败" << endl;
exit(-1);