leecode 解题总结:37 Sudoku Solver

来源:互联网 发布:医院感染控制软件 编辑:程序博客网 时间:2024/06/05 17:05
#include <iostream>#include <stdio.h>#include <vector>#include <fstream>using namespace std;/*问题:Write a program to solve a Sudoku puzzle by filling the empty cells.Empty cells are indicated by the character '.'.You may assume that there will be only one unique solution.A sudoku puzzle......and its solution numbers marked in red.分析:这是搜索是否有解的问题,广度优先搜索最优解,深度优先搜索确定是否有解。因此本题应该用深度优先搜索。看题目,如果摆放新的元素不成功,应该是要回溯的。因此,此题应该是回溯来做。每一次尝试摆放一个1~9中的某个元素,如果摆放不成功,就用另一个元素替换,如果最终棋盘摆满了,就输出结果。如何判定没有结果,如果1判断是否满足可行解,只需要当前board[i][j]元素为c是否在行号,列号,子棋盘摆放过判断子棋盘上的9个元素是否与给定元素重复,先确定 子棋盘的行号=行号给定位置(row,jcol)计算对应子棋盘的行号(x,y)x = 3 * (row / 3)y = 3 * (col / 3)子棋盘编号 = 3 *(row / 3) + col /3 = 3 + 2 = 5,行号确定大的子棋盘编号,列号确定小的子棋盘编号子棋盘元素下标 = 3 * (col / 3) + col % 3 = 3 * 2 + 8 % 3 = 8,其实就是将列分成3等份,然后取余数比如给定元素(5,8),对应第6子棋盘中(编号为5)中第8个元素这里由于采用i为0~8,i默认为列号则新的子棋盘编号=board[ 3 * (row / 3) + i / 3 ][3 * (col / 3) + i % 3]subBoardIndex = 3 * (row / 3) + i / 3;index = 3 * (col / 3) + i % 3;*/class Solution {public:bool isValidSudoku(vector<vector<char> > &board , int row  , int col , char c){if(board.empty()){return false;}int size = board.size();int subBoardIndex;int index;for(int i = 0 ; i < 9 ; i++){if(board[i][col] != '.' && board[i][col] == c){return false;}if(board[row][i] != '.' && board[row][i] == c){return false;}/*判断子棋盘上的9个元素是否与给定元素重复,先确定 子棋盘的行号=行号给定位置(row,jcol)计算对应子棋盘的行号(x,y)x = 3 * (row / 3)y = 3 * (col / 3)子棋盘编号 = 3 *(row / 3) + col /3 = 3 + 2 = 5,行号确定大的子棋盘编号,列号确定小的子棋盘编号子棋盘元素下标 = 3 * (col / 3) + col % 3 = 3 * 2 + 8 % 3 = 8,其实就是将列分成3等份,然后取余数比如给定元素(5,8),对应第6子棋盘中(编号为5)中第8个元素这里由于采用i为0~9,i默认为列号则新的子棋盘编号=board[ 3 * (row / 3) + i / 3 ][3 * (col / 3) + i % 3]*/subBoardIndex = 3 * (row / 3) + i / 3;index = 3 * (col / 3) + i % 3;if(board[subBoardIndex][index] != '.' && board[subBoardIndex][index] == c){return false;}}return true;}bool isSolved(vector<vector<char>>& board){if(board.empty()){return false;}int size = board.size();for(int i = 0 ; i < size ; i++){for(int j = 0 ; j < size ; j++ ){if('.' == board.at(i).at(j)){//尝试在空白的区域处摆放下一个元素,这里直接用chafor(char c = '1' ; c <= '9' ; c++){//如果摆放有效,继续处理if(isValidSudoku(board , i , j , c)){board.at(i).at(j) = c;//牛逼,直接用递归判断下一次是否摆放成功if(isSolved(board)){return true;}else{board.at(i).at(j) = '.';}}}//如果一直没有得到结果,说明无效return false;}}}return true;}    void solveSudoku(vector<vector<char>>& board) {if(board.empty()){return;}bool isSolve = isSolved(board);_isSolved = isSolve;}public:bool _isSolved;};vector<string> readFile(string& fileName){vector<string> results;if(fileName.empty()){return results;}ifstream file(fileName , ios::in);if(!file){cout << "can't open file" << endl;return results;}const int maxSize = 1024;char str[maxSize];while(!file.eof()){file.getline(str , maxSize);string s(str);results.push_back(s);}file.close();return results;}void print(vector< vector<char> >& board){if(board.empty()){cout << "no result" << endl;}int size = board.size();for(int i = 0 ; i < size ; i++){for(int j = 0 ; j < size ; j++ ){cout << board.at(i).at(j);}cout << endl;}}void process(){vector< vector<char> > board;string s;int size;Solution solution;board.clear();vector<string> strs = readFile(string("data.txt"));int len = strs.size();for(int i = 0 ; i < len ; i++){s = strs.at(i);vector<char> str;size = s.length();for(int i = 0 ; i < size ; i++){str.push_back(s.at(i));}board.push_back(str);}solution.solveSudoku(board);if(solution._isSolved){print(board);}else{cout << "no" << endl;}}int main(int argc , char* argv[]){process();getchar();return 0;}

0 0