首页 > 学院 > 开发设计 > 正文

leecode 解题总结:37 Sudoku Solver

2019-11-10 18:02:41
字体:
来源:转载
供稿:网友
#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))				{					//尝试在空白的区域处摆放下一个元素,这里直接用cha					for(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;}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表