数独的含义

根据9宫格盘面上的已知数字,推理出所有剩余空格的数字。
标准数独:使每个数字在每一行、每一列和每一宫中都仅出现一次。
异型数独:在满足标准数独的规则上,额外添加其他约束条件。

变量的定义

flag:二维数组,代表数独在初始状态中空白的区域
rule:三维数组,表示每种规则->每个位置->每个数值的占用情况
sudoku:二维数组,用于存储数独的数字分布状态

标准数独需三种规则, 如:每行->第几行->哪个数字=是否已占用(0未占用/1已占用)
异型数独可自行拓展, 如:对角线->第几条对角线->哪个数字=是否已占用(0未占用/1已占用)

算法思路

  1. 读取数独的初始状态,填入sudoku变量
  2. 在读取数独的初始状态的同时,初始化数字的可填区域,填入flag变量
  3. 在读取数独的初始状态的同时,更新每种规则占用情况,填入rule变量
  4. (0, 0)开始求解数独,进入首层递归
  5. 遍历flag,获取下一个可填区域的位置
  6. 若当前位置已超出期望,表明已得出数独的解,打印结果并回溯到上一层进行求解
  7. 从指定数字开始,与当前位置的所有规则的交集进行对比,获取下一个可填数字
  8. 修改当前位置的可填数,如果该数值为无效取值,则回溯到上一层进行求解
  9. 更新每种规则的占用状态为已占用
  10. 以当前的坐标作为实参进入下一层递归,返回步骤5
  11. 更新每种规则的占用状态为未占用

数独样本

  • 根据上图,转换为程序输入文本结构:
009008040
600000017
010040000
000000004
480603021
300000000
000090080
240000006
050700100

参考代码

#include <iostream>
#include <string>
#include <ctime>using namespace std;int rule[3][9][9], sudoku[9][9], flag[9][9];int findSmallIndex(int rowIndex, int colIndex) {return (3 * (rowIndex / 3) + (colIndex / 3));
}int findNextValue(int rowIndex, int colIndex, int start) {int index = findSmallIndex(rowIndex, colIndex);for (int i = start; i < 9; i++) {if (rule[0][rowIndex][i]) continue;if (rule[1][colIndex][i]) continue;if (rule[2][index][i]) continue;return i;}return -1;
}void changeRule(int rowIndex, int colIndex, int style) {int index = findSmallIndex(rowIndex, colIndex);int value = sudoku[rowIndex][colIndex];rule[0][rowIndex][value] = style;rule[1][colIndex][value] = style;rule[2][index][value] = style;
}void initSudoku() {for (int i = 0; i < 9; i++) {for (int j = 0; j < 9; j++) {sudoku[i][j] = getchar() - '0' - 1;flag[i][j] = sudoku[i][j] == -1 ? 1 : 0;if (!flag[i][j]) changeRule(i, j, 1);}getchar();}
}void show() {string result;for (int i = 0; i < 81; i++) {result += to_string(sudoku[i / 9][i % 9] + 1);if (i % 9 == 8) result += "\n";}cout << result << endl;
}void solve(int index) {int rowIndex, colIndex;while (index < 81) {rowIndex = index / 9;colIndex = index % 9;if (flag[rowIndex][colIndex] == 1) break;index++;}if (index == 81) {show(); return;}while (true) {sudoku[rowIndex][colIndex] = findNextValue(rowIndex, colIndex, sudoku[rowIndex][colIndex] + 1);if (sudoku[rowIndex][colIndex] != -1) {changeRule(rowIndex, colIndex, 1);solve(index + 1);changeRule(rowIndex, colIndex, 0);} else {break;}}
}int main() {long time1, time2;initSudoku();time1 = clock();solve(0);time2 = clock();cout << "求解过程共用" << time2 - time1 << "毫秒" << endl;return 0;
}

算法评测

  • 无冗余代码,无重复计算,代码可读性良好
  • 可求解数独的所有解
  • 对已知规则进行交集运算,快速得到下一个有效数字,缩减查询时间
  • 求解速度快,数独初始状态全0的情况下,1秒可得40W组解
  • 空间占用少,数独初始状态全0的情况下,CPU:25%,内存:360KB

回溯算法高效解标准数独(MarkDown)相关推荐

  1. 回溯算法详解之全排列、N皇后问题

    回溯算法详解 回溯算法框架.解决一个回溯问题,实际上就是一个决策树的遍历过程.你只需要思考 3 个问题: 1.路径:也就是已经做出的选择. 2.选择列表:也就是你当前可以做的选择. 3.结束条件:也就 ...

  2. 面试题目_经典面试题目「回溯算法」解数独

    解数独,理解二维递归是关键! 通知:我将公众号文章和学习相关的资料整理到了Github :https://github.com/youngyangyang04/leetcode-master,方便大家 ...

  3. 五大常用算法——回溯算法详解及经典例题

    回溯算法 1.回溯算法就是一种有组织的系统最优化搜索技术,可以看作蛮力法穷举搜索的改进.回溯法常常可以避免搜索所有可能的解,所以它适用于求解组织数量较大的问题. 2.首先我们先了解一下一个基本概念&q ...

  4. 回溯算法详解:理论+基础类回溯题解

    文章目录 五:括号生成问题 六:组合总和(点击跳转) 七:子集问题(点击跳转) 五:括号生成问题 这个问题也比较经典,题目的要求是让你生成所有可能的并且 有效的 括号组合. 对于括号问题,两个特性,请 ...

  5. [人工智能]回溯算法解数独

    今天在AI课上学了CSP,然后学了回溯算法.所以就用回溯算法来解数独吧. 数独问题可以把九九八十一个格简化为81个变量,每一个变量可以取1-9的值,当然,一开始初始化的值是不可以改变的.然后呢,对于这 ...

  6. 回溯算法解数独问题(java版)

    下面来详细讲一下如何用回溯算法来解数独问题. 下图是一个数独题,也是号称世界上最难的数独.当然了,对于计算机程序来说,只要算法是对的,难不难就不知道了,反正计算机又不累.回溯算法基本上就是穷举,解这种 ...

  7. 高效 遍历 算法_一文学会回溯算法解题技巧

    (给算法爱好者加星标,修炼编程内功) 来源:码海 前言 上文我们学习了深度优先搜索和广度优先搜索,相信大家对这两者的算法有了比较清楚的认识,值得一提的,深度优先算法用到了回溯的算法思想,这个算法虽然相 ...

  8. labuladong的算法小抄_学会了回溯算法,我终于会做数独了

    经常拿回溯算法来说事儿的,无非就是八皇后问题和数独问题了.那我们今天就通过实际且有趣的例子来讲一下如何用回溯算法来解决数独问题. 一.直观感受 说实话我小的时候也尝试过玩数独游戏,但从来都没有完成过一 ...

  9. 回溯算法解子集、组合、排序

    转载labuladong:力扣 代码方面,回溯算法的框架: result = [] def backtrack(路径, 选择列表):if 满足结束条件:result.add(路径)returnfor ...

  10. 「leetcode」最强回溯算法总结篇!历时21天、画了20张树形结构图、14道精选回溯题目精讲

    本文 https://github.com/youngyangyang04/leetcode-master 已经收录,里面还有leetcode刷题攻略.各个类型经典题目刷题顺序.思维导图,可以fork ...

最新文章

  1. Mysql列类型-数值型
  2. JavaScript学习记录 (三) 函数和对象
  3. PHP7Grafika,PHP图片处理库Grafika详细教程(3):图像属性处理
  4. linux mysql 释放x锁_MySQL 加锁处理分析-转载
  5. Spring boot 启动过程
  6. Arduino 002 --- 在Ubuntu(Linux) 中搭建Arduino开发环境
  7. IP,IP地址,mac地址
  8. 微信开发经常会用到的一些方法
  9. Android代码中模拟点击事件
  10. 无线网络技术复习笔记(5)——无线城域网、广域网
  11. Python 微信自动发送消息
  12. Python学习_基础_29_面向对象编程之多态、鸭子类型
  13. SLAM高翔视频第二讲萝卜习题
  14. Notes Twenty-third days-渗透攻击-红队-红队自研
  15. 推荐一个数据库文档生成神器
  16. 为什么角膜塑形镜的价格比隐形眼镜贵这么多?
  17. 安装Power BI Desktop在线报错关于windows10家庭版更新中遇到的 “你的设备中缺少重要的安全和质量修复”问题
  18. 草根IT对博客模板MaterialDesign的优化
  19. 【递归】进制转换、字符串反转、判断回文
  20. WordCount单词计数详解

热门文章

  1. 计算机技术中储存容量最大的单位,计算机中最大单位是什么
  2. Hadoop版本比较
  3. java制作摇奖系统_基于Java实现抽奖系统
  4. 创业维艰-公司业务解决方案推荐!
  5. 5分钟三句代码实现抖音自动下载
  6. js逆向爬虫入门-01.微信公众平台模拟登录逆向
  7. Android WebView实现长截图
  8. spire.pdf修改pdf内容
  9. python 科学计算地磁_用Python控制硬件32-用HMC5883L测量地磁场强度
  10. 【Python-tkinter】拼音输入方法——小学拼音练习题