数独求解 Sudoku Solver
来源:互联网 发布:如何退出手机淘宝账号 编辑:程序博客网 时间:2024/04/29 13:00
数独游戏是个经典的游戏。现在我要通过程序的方法才自动求解一个数独。这个问题在《Puzzles for Programmers and Pros》一书中有讲解。
思路:
最直接的方法是,可以用backtracking进行递归尝试。一旦探测到错误就回溯,最终将在递归的最深处发现正解。
注意backtracking是可以用引用类型参数进行递归深入的,但是递归回溯出来的时候一定要将改变的值回复回原样,这样下一轮的尝试才不会受到影响。
纯粹的递归尝试就相当于穷举法,速度非常慢。想想人脑做数独的时候是怎么进行的?肯定不是上面的方法。而是先找出最容易写出答案的。对于一个位置,如果发现其同行、同列、同方格中已经把9个数的8个都使用过了,那么必然的,这个位置具有唯一的答案。依照这个方法进行重复,可以先把数独填上若干。
当找不到具有唯一确定答案的位置的时候,意味着就必须要尝试性的推测了。这时候,我就找推测范围最小的位置进行尝试。因为范围越小,成功概率越大。这样可以尽量减少错误的递归次数。
代码:
#include <iostream>#include <vector>#include <string>using namespace std;vector<char> checker(vector<vector<char> > &board, int row, int col){ vector<char> posibile; int bitmap[9]; memset(bitmap, 0, sizeof(bitmap)); int i; for(i=0;i<9;i++) if(board[row][i] != '.') bitmap[board[row][i] -'1'] = 1; for(i=0;i<9;i++) if(board[i][col] != '.') bitmap[board[i][col] - '1'] = 1; int row_base = (row/3)*3; int col_base = (col/3)*3; for(int i = 0;i<3;i++) for(int j=0;j<3;j++) { if(board[row_base + i][col_base + j] != '.') bitmap[board[row_base + i][col_base + j] - '1'] = 1; } for(i=0;i<9;i++) if(bitmap[i] == 0) { posibile.push_back(char('1' + i)); } return posibile;}bool fun(vector<vector<char> > &board){ size_t min = 10; vector<char> minoption; int mini, minj; // 寻找一个推测范围最小的位置 for(int i=0;i<9;i++) for(int j=0;j<9;j++) { if(board[i][j] != '.') continue; vector<char> option = checker(board, i, j); if(option.size() < min) { min = option.size(); minoption = option; mini = i; minj = j; } } if(min == 10) return true; //min没有改变,可见所有都填满 // 对推测范围最小的位置进行递归尝试 for(int k=0;k<minoption.size();k++) { board[mini][minj] = minoption[k]; if(fun(board)) return true; board[mini][minj] = '.'; } return false; //这儿很关键!!因为并非option里一定有正确答案,因为可能是之前的数放错了}void solveSudoku(vector<vector<char> > &board){ if(board.size() != 9) return; bool flag = true; while(flag) { flag = false; for(int i=0;i<9;i++) { for(int j=0;j<9;j++) { if(board[i][j] == '.') { vector<char> tmp = checker(board, i, j); if(tmp.size() == 1) { board[i][j] = tmp[0]; flag = true; } } } } } fun(board);}void show(vector<vector<char> > &board){ for(int i=0;i<9;i++) { for(int j=0;j<9;j++) cout<<board[i][j]<<" "; cout<<endl; } cout<<endl;}int main(int argc, const char * argv[]){ vector<vector<char> > board; vector<char> t; string s[9] = {"..9748...","7........",".2.1.9...","..7...24.",".64.1.59.",".98...3..","...8.3.2.","........6","...2759.."}; for(int i=0;i<9;i++) { for(int j=0;j<9;j++) t.push_back(s[i][j]); board.push_back(t); t.clear(); } show(board); cout<<"start..."<<endl; solveSudoku(board); cout<<"over"<<endl; show(board); return 0;}
1 0
- 数独求解 Sudoku Solver
- Sudoku Solver:数独求解
- LeetCode: Sudoku Solver (数独求解)
- Sudoku Solver 求解数独问题
- 【LeetCode】37. Sudoku Solver 数独求解
- LeetCode 37 Sudoku Solver(求解数独)(*)
- Leetcode #37. Sudoku Solver 数独求解 结题报告
- Leetcode-Sudoku Solver(数独)
- LeetCode Sudoku Solver 数独C++程序
- [LeetCode] [数独问题] Sudoku Solver
- Sudoku Solver 数独的解决方案
- 36/37. Sudoku Solver 数独问题
- LeetCode:Valid Sudoku,Sudoku Solver(数独游戏)
- leetcode_Valid Sudoku and Sudoku Solver (数独游戏) _easy
- leetcode 37. Sudoku Solver 36. Valid Sudoku 数独问题
- 用SQL求解数独(Sudoku)
- 数独(sudoku)游戏的程序求解
- 数独(Sudoku)求解程序
- 找工作日记之第一天(腾信创软,天源迪科)
- libevent源码分析---让libevent支持多线程
- 利用PhoneGap技术将“捕鱼达人”网页游戏移植到Android手机
- Handler线程消息处理逻辑
- Java 字体控制
- 数独求解 Sudoku Solver
- 定位.语言在这里为工具,忽略细节。
- windows编译taglib1.91
- Java知识点总结——装箱与拆箱
- 虽然用了好几年的CSDN了,却是第一次在这上面写博客
- C语言二叉排序树单词计数程序实现
- 八中oj——2176【NOI2001】聪明的打字员 代码
- 鼠标右键怎么清除Catalyst Control Center
- C++ 对象占用内存大小的思考