解9*9数独算法(C++)
什么是数独
数独(shù dú)是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。已知有9行9列的格子,且被分成9个3*3的方块。其中一些格子内有数字,数值的范围为1-9 。玩家需要在其余的空白格子上填入数字,数字的范围也是1-9,要求所有空格都被填满而且满足以下条件:
- 数字 1-9 在每一行只能出现一次。
- 数字 1-9 在每一列只能出现一次。
- 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
例如:
一个数独题目如下:
一种解法如下:
红色数字为玩家填入的答案,满足每一行、每一列、每一个3*3黑边方块内所有的数字不重复。
解题方法
大体方向
找出当前的各种解法,不断地填入可能的数字,如果证实解法错误则撤回,继续尝试其他解法。
使用递归的方法,尝试各个可能的解,并且向上一层返回尝试的结果(成功或者失败)。
递归函数的处理过程如下:
- 如果数独已经完成,则大功告成。向上一层返回成功的信息。
- 推测出每一空白格的可能填入的数字。
- 找到可选数字最少的那一格。
- 如果有可选的数字,到步骤 5,否则返回失败的信息 。
- 填入一个可能的数字,生成新的数独。
- 调用递归函数处理新的数独,跳到下一层步骤 1。
- 得到下一层的返回信息,如果是失败跳到步骤 8,否则返回成功的信息。
- 如果还有下一个可选的数字,跳到步骤 5,否则返回失败的信息。
相关技巧
- 利用ASCII编码 和 减法 来把字符转数字,如 ‘1’ - ‘0’ 得到数值 1 。
- 使用位来记录数字1-9,可以用 unsigned int 类型从右往左数的第k位代表数字k。
- 使用数字 1 左移来定位相应的位,如 1 << k 代表右往左数的第 k+1 位。
- 使用 或运算 和 与运算 来操作相关的位。
- 对于 i 行 j 列的小方格,使用 i / 3 * 3 + j / 3 即可以得出相应3 * 3方块的下标。
- 使用__builtin_ctz() 函数可以迅速得出变量二进制表示时,末尾0的数量。
- 使用__builtin_popcount() 函数可以迅速得出变量二进制表示时1的数量。
代码分享
class Solution {public:void solveSudoku(vector<vector<char>>& board) {unsigned int pos_r[9];//每一行剩下的可选数字unsigned int pos_l[9];//每一列剩下的可选数字unsigned int pos_b[9];//每一方块剩下的可选数字//一开始九个数字都是可选的,9个位全部为1for (int i = 0; i < 9; i++){pos_r[i] = 0b111111111;pos_l[i] = 0b111111111;pos_b[i] = 0b111111111;}for (int i = 0; i < 9; i++){for (int j = 0; j < 9; j++){if(board[i][j] != '.' ){//出现了新的数字,空白格用点号表示unsigned int bit = 1 << (board[i][j] - '1');pos_r[i] &= ~bit;//把相应的位置为0pos_l[j] &= ~bit;pos_b[i/3*3+j/3] &= ~bit;}}}slove(board, pos_r, pos_l, pos_b);//调用函数}bool slove(vector<vector<char>>& board, unsigned int *pos_r, unsigned int *pos_l, unsigned int *pos_b){int min_choice = 10;int a = 0, b = 0;unsigned int pos_bit = 0;for (int i = 0; i < 9; i++){for (int j = 0; j < 9; j++){if(board[i][j] == '.' ){//该位置没有填unsigned int possible = pos_r[i] & pos_l[j] & pos_b[i/3*3+j/3];//计算出同时满足三个条件的数字if (possible == 0) return false;//无解int choice = __builtin_popcount(possible);//计算可能的数字有多少(1的位数)if (choice < min_choice){//找到可填入数字最少的min_choice = choice;a = i;b = j;pos_bit = possible;}}}}if (min_choice == 10) return true; //全部填完了,返回//pos_bit 记录可能的数字while(pos_bit){unsigned int test_bit = 1 << __builtin_ctz(pos_bit);//从最右边的位开始(选最小的数字)board[a][b] = __builtin_ctz(pos_bit) + '1';//填入数字pos_r[a] &= ~test_bit;pos_l[b] &= ~test_bit;pos_b[a/3*3+b/3] &= ~test_bit;if (slove(board, pos_r, pos_l, pos_b)){return true;//成功 返回}//失败,撤回后继续试board[a][b] = '.';pos_r[a] |= test_bit;pos_l[b] |= test_bit;pos_b[a/3*3+b/3] |= test_bit;//清除试过的位pos_bit &= ~test_bit;}return false;//找不到解}
};
解9*9数独算法(C++)相关推荐
- 花了1晚上diy的matlab解数独算法,很好理解!
花了1晚上diy的matlab解数独算法,很好理解! 前言 一.数独的规则 二.算法 1.思路 2.流程图 3.Matlab代码 总结 前言 老婆最近迷上了数独,还给我拍了张照片,初步了解了规则之后, ...
- 数独算法-递归与回溯
1.概述 数独(Sudoku)是一种运用纸.笔进行演算的逻辑游戏.玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个粗线宫内的数字均含1-9,不重复. 1)终盘 ...
- python回溯法解9*9数独
文章目录 前言 一.回溯法解数独代码 总结 前言 看了labuladong算法小抄里的回溯法,照着模板,加入自己的理解,用python做了个解9*9数独的回溯法,. 一.回溯法解数独代码 直接上代码: ...
- java课程 数独 文库_通俗易懂的数独算法(java版)
数独算法 一 知识背景 无 二 绪言 偶尔玩下休闲益智小游戏,一方面可以舒解下心情,另一方面刺激下大脑皮层.百度了一下数独的起源和概念.说了那么多,看着就累.精简一下就是数字(0-9)填充游戏.不明白 ...
- “论解不了数独所以选择做个数独游戏这件事”
有一天,小明同学在津津有味的逛力扣网站的时候,惊喜的发现了一个看似非常好下手的题目(万恶之源 T T). 于是小明同学又津津有味的写了解题思路. 像往常一样打开了Unity准备开始做. .(画UI) ...
- C++ sodoku solve数独算法(附完整源码)
sodoku solve数独算法 sodoku solve数独算法的完整源码(定义,实现,main函数测试) sodoku solve数独算法的完整源码(定义,实现,main函数测试) #includ ...
- 完成数独的算法 python_python实现数独算法实例
本文实例讲述了python实现数独算法的方法.分享给大家供大家参考.具体如下: # -*- coding: utf-8 -*- ''' Created on 2012-10-5 @author: Ad ...
- 用python设计数独的心得体会_python实现数独算法实例
本文实例讲述了python实现数独算法的方法.分享给大家供大家参考.具体如下: # -*- coding: utf-8 -*- ''' Created on 2012-10-5 @author: Ad ...
- python:实现9×9二维数组数独算法(附完整源码)
python:实现9×9二维数组数独算法 from __future__ import annotationsMatrix = list[list[int]]# assigning initial v ...
最新文章
- python小游戏系列记忆宫殿,儿时的回忆
- Python IDLE启动报错
- Shiro之从数据库初始化角色权限信息
- spark1.0和2.0的区别_【系统】华为正式发布鸿蒙OS 2.0手机Beta版:UI界面、交互无区别...
- 分析java 线程占用内存_Java线程:保留的内存分析
- java学习(82):静态代码块内部类
- VS2010 C++编译报错LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
- Git 的安装及配置
- html转义 在线,HTML转义工具 [Javascript版]
- MSDN官方数据库开发群
- 智能优化算法论文python复现,附代码--鲸鱼优化算法(WOA)-1
- WAP1.X/WAP2.0以及WAP浏览器的协议版本
- 解决 Android App 上架 Google play后 ,签名变更,第三方sdk无法登录
- 【转】智能家居 系统安装及HA系统介绍
- GPU 编程与CG 语言之阳春白雪下里巴人——CG学习读书笔记之数学函数(三)
- scanf ---------未完待续
- 计算机专业学习规划,计算机专业学习计划.doc
- 文本表示(一)—— word2vec(skip-gram CBOW) glove, transformer, BERT
- VS Code中使用PlantUML绘图
- AForge学习笔记(5):AForge.Imaging(下)
热门文章
- 启动kafka2.8报afka.common.KafkaException: No `meta.properties` found in /tmp/kraft-combined-logs
- NC-Verilog仿真
- PRD(Product Requirement Document,产品需求文档)模板
- scala面向对象基础---类继承和特质
- 基于C++的简易RLC电路仿真器与滤波器仿真测试
- qt中在QLabel上显示图像并画矩形框。
- 《MySQL必知必会》第8篇:存储过程、函数
- SPSS显著性差异分析及字母标记
- iMX6UL配置MCP2515模块(SPI转CAN)——基于迅为iTOP-iMX6UL开发板
- 自然生长不含咖啡碱的茶树新品种--T三有机可可茶