数独问题的c++解决
来源:互联网 发布:淘宝上退款多久能到账 编辑:程序博客网 时间:2024/05/19 20:20
今天在刷leetcode的时候遇见一道难度为hard的题目,大意是解出给定的数独。感觉比较有应用的价值,便尝试着去做了一下。
首先明确数独问题必有唯一可行解。求数独有效解的基本思想是利用回溯法:从挖空的地方开始,从1到9逐个地去尝试可能的解。如果当前行、列以及所在大方格没有出现重复,则解被暂时接受,并开始尝试以相同的方式求解下一个空格。如果1到9均不成为有效解,则后退至上一个空格,试探其下一个可能值。以下面一个简单的数独为例:
搜索空格。在(1,3)处出现空格。从“1”开始试探,发现“2”符合要求,将其暂时填入,并搜索下一个空格(1,4)。发现符合条件的数为“6”,将其填入空格。如下图所示:
此时开始搜索第三个空格(1,9),发现1到9中无合适的数字可填入其中,故回退至上一“空格”处(1,4),此时同样发现可行解也已搜索完毕,故再回退至上上空格(1,3)处,搜索得下一可能值4,将其填入,如下所示:
此时其他空格便迎刃而解了。具体实现的代码如下:
class Solution {public: bool isvalid(vector<vector<char>>& board, int row, int column, char test){ //检查新添加的元素是否符合数独要求 int st1=row/3*3,st2=column/3*3; //同一方块下的首元素位置坐标 for(int i=0;i<9;i++) { if(board[i][column]==test) return false; //检查同一列 if(board[row][i]==test) return false; //检查同一行 if(board[st1+i/3][st2+i%3]==test) return false; //检查同一方块 } return true; } bool solve(vector<vector<char>>& board) { int rows=board.size(),columns=board[0].size(); for(int i=0;i<rows;i++) for(int j=0;j<columns;j++) { if(board[i][j]=='.') { for(char c='1';c<='9';c++) //逐个尝试 { if(isvalid(board,i,j,c)) //初步尝试 { board[i][j]=c; if(solve(board)) return true; else board[i][j]='.'; //回溯 } } return false; //如果九个数都试过还是不符合要求,则需要回溯 } } return true; //此时已无空格 } void solveSudoku(vector<vector<char>>& board) { //使用回溯法解决 solve(board); }};经过测试,发现五个case的解答时间平均为13ms。该算法的时间复杂度为O(9^N),其中N是未知空格数。不难发现,在程序中很多地方进行了重复的遍历,仍有进行剪枝以进一步降低运行时间的可能。考虑用三个数组分别记录每一行、每一列以及每一个大方格内出现数字的情况,并将数独内所有挖空处的行列信息统一用一个数组保存,减少重复遍历。具体实现代码如下所示:
class Solution {public: bool solver(vector<vector<char>>& board,int index,vector<pair<int,int>>& empt, vector<vector<bool>>& row, vector<vector<bool>>& column, vector<vector<bool>>& region) { if(index==empt.size()) return true; //此时已找到所有空格上所应填的数 int r=empt[index].first,c=empt[index].second; for(int a=0;a<9;a++) { if(!row[r][a]&&!column[c][a]&&!region[r/3*3+c/3][a]) //如果没有重复 { row[r][a]=true; column[c][a]=true; region[r/3*3+c/3][a]=true; board[r][c]='1'+a; if(solver(board,index+1,empt,row,column,region)) return true; //表明一路返回的都是true else { row[r][a]=false; //否则,需要将状态还原以回溯 column[c][a]=false; region[r/3*3+c/3][a]=false; board[r][c]='.'; } } } return false; //遍历了所有可能性仍然没有符合要求的结果 } void solveSudoku(vector<vector<char>>& board) { //依然是回溯法,不过用空间换时间,进行了一定程度的剪枝 vector<vector<bool>> row(9,vector<bool>(9,false)); //记录每一行的数字是否已经出现过的情况 vector<vector<bool>> column(9,vector<bool>(9,false)); vector<vector<bool>> region(9,vector<bool>(9,false)); vector<pair<int,int>> empt; //记录需要填满的空格的坐标 int l1=board.size(),l2=board[0].size(); for(int i=0;i<l1;i++) for(int j=0;j<l2;j++) //所有数据进行初始化 { if(board[i][j]=='.') { empt.push_back({i,j}); } else { int num=board[i][j]-'1'; row[i][num]=true; column[j][num]=true; region[i/3*3+j/3][num]=true; } } solver(board,0,empt,row,column,region); }};经过测试,相同case下时间降到了6ms,达到了预期的效果。
阅读全文
0 0
- DLX之数独问题的解决
- 数独问题的c++解决
- C语言 递归(回溯) 解决数独问题
- C语言递归解决数独
- 数独问题的解决办法
- 数独问题的方法
- [LeetCode]SudokuSolver解决数独问题
- gac算法解决数独问题
- 数独的解法c语言
- 数独问题思考
- 数独问题
- cs101,数独问题
- 数独问题
- 4.9 数独问题
- 数独问题
- hdu - 数独问题
- 数独问题
- 算法 数独问题
- 多线程
- apaceh2.4虚拟多站点httpd-vhosts.conf
- 数的子结构
- 常用集合类总结(java)
- 【JavaSE_学习笔记】BigDecimal类与BigInteger类
- 数独问题的c++解决
- Maven基础
- [caffe使用]caffe使用中可能遇到的问题总结
- Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
- Angular4 中显示内容的 CSS 样式
- 在UITableView的header上加阴影
- Android实现闪屏页面+视频引导页
- leetcode10 Regular Expression Matching @python
- linux系统之逻辑卷管理器LVM建立以及LVM相关操作