LeetCode Sudoku Solver

早就见过数独的题了,一看就头疼,也没认真看过,这里遇见了,好似久违的敌人和朋友,终于可以切磋一下了。想到了回溯法,没想用,看了几个例子在这上面的http://www.sudokuhints.com/,这里的例子确实特别好,而且易懂,想看看有没有什么规律,果然找到了规律(简单说来就是:寻找那些独一无二的点,即某些点只能有一个唯一的值才满足横约束、竖约束和3*3小格子约束,一个一个点判断,寻找这样的点先填入,然后判断是否所有点都填完了,所有点都填完了就完成了数独),一晚上的时间实现了,测了几个例子都好使,提交上去了却不行了。调试了一下,问题是:有些题目(可能是由于给的点少了一点)会出现死循环,就是不存在任何唯一的点(这样的题目应该是有超出一个解的),所以程序没法执行了,可能程序已经填了好多点,只是生一小部分的点有不唯一。比如例子["..9748...","7........",".2.1.9...","..7...24.",".64.1.59.",".98...3..","...8.3.2.","........6","...2759.."]

这是题目给的。用我的程序处理后只能到这里:此时程序找不到唯一的点了。我倒没想到更好地解决这问题(其实解决这问题就是对那些可能的点进行测试了,这其实就是回溯了,估计也只能回溯了)。但由于我的程序没有递归速度应该更快。于是就做了个实验,把题目的数独先用我的程序跑一遍,再用回溯法,果然结果如下:

是快了不少,所有程序和例子如下:

// LeetCode_ValidSudoku.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <set>
#include <map>
using namespace std;

bool isValidSudoku(vector<vector<char> > &board) {
	map<char,int> mp;
	for (int i=0;i<9;i++)
	{
		mp.clear();
		for (int j=0;j<9;j++)
		{
			mp[board[i][j]]++;
			if (mp[board[i][j]]>1&&board[i][j]!='.')
			{
				return false;
			}
		}
	}
	for (int j=0;j<9;j++)
	{
		mp.clear();
		for (int i=0;i<9;i++)
		{
			mp[board[i][j]]++;
			if (mp[board[i][j]]>1&&board[i][j]!='.')
			{
				return false;
			}
		}
	}
	for (int m=0;m<9;m+=3)
	{
		for (int n=0;n<9;n+=3)
		{
			mp.clear();
			for (int i=m;i<m+3;i++)
			{
				for (int j=n;j<n+3;j++)
				{
					mp[board[i][j]]++;
					if (mp[board[i][j]]>1&&board[i][j]!='.')
					{
						return false;
					}
				}
			}
		}
	}
	return true;
}

set<char> exceptValueSet(vector<vector<char> > &board,int m,int n)
{
	//cout<<" in exceptValueSet "<<endl;
	set<char> ret;
	for (int i=0;i<9;i++)
	{
		if (board[m][i]!='.')// m row
		{
			ret.insert(board[m][i]);
		}
	}
	for (int i=0;i<9;i++)
	{
		if (board[i][n]!='.')//n column
		{
			ret.insert(board[i][n]);
		}
	}
	int p=0,q=0;
	while(p<=m) p+=3;
	while(q<=n) q+=3;
	p -= 3;
	q -= 3;
	for (int i=p;i<p+3;i++)
	{
		for (int j=q;j<q+3;j++)
		{
			if (board[i][j]!='.')//3*3 grid
			{
				ret.insert(board[i][j]);
			}
		}
	}
	return ret;
}
bool testRowUnique(vector<vector<char> > &board,int row,char ch)
{
	//cout<<" in testRowUnique "<<endl;
	for(int i=0;i<9;i++)
	{
		if (board[row][i]==ch)
		{
			return true;
		}
	}
	return false;
}
bool testColumnUnique(vector<vector<char> > &board,int column,char ch)
{
	//cout<<" in testColumnUnique "<<endl;
	for(int i=0;i<9;i++)
	{
		if (board[i][column]==ch)
		{
			return true;
		}
	}
	return false;
}
bool testGridUnique(vector<vector<char> > &board,int m,int n,char ch)//test row and column,once conflict return false;
{
	for (int i=0;i<9;i++)
	{
		if (board[m][i]==ch)
		{
			return false;
		}
	}
	for (int i=0;i<9;i++)
	{
		if (board[i][n]==ch)
		{
			return false;
		}
	}
	return true;
}
bool testUnique(vector<vector<char> > &board,int m,int n,char ch)
{
	//cout<<" in testUnique "<<endl;
	int p=0,q=0;
	while(p<=m) p+=3;
	while(q<=n) q+=3;
	p -= 3;
	q -= 3;
	for (int i=p;i<p+3;i++)//row testunique
	{
		if (i!=m&&board[i][n]=='.')//3*3 grid
		{
			if (!testRowUnique(board,i,ch))
			{
				return false;
			}
		}
	}
	for (int j=q;j<q+3;j++)
	{
		if (j!=n&&board[m][j]=='.')//colun testunique
		{
			if (!testColumnUnique(board,j,ch))
			{
				return false;
			}
		}
	}
	for (int i=p;i<p+3;i++)
	{
		for (int j=q;j<q+3;j++)
		{
			if (i==m&&j==n)
			{
				continue;
			}
			if (board[i][j]=='.')//3*3 grid means that each ij should be invalid except for mn
			{
				if (testGridUnique(board,i,j,ch))//if there is one can be placed in the i j position then not unique
				{
					return false;
				}
			}
		}
	}
	return true;
}
bool isFinished(vector<vector<char> > &board)
{
	for (int i=0;i<9;i++)
	{
		for (int j=0;j<9;j++)
		{
			if (board[i][j]=='.')
			{
				return false;
			}
		}
	}
	return true;
}
void solveSudoku1(vector<vector<char> > &board) {
	set<char> expValueSet;
	bool flag = true;
	while(!isFinished(board)&&flag)
	{
		flag = false;
		for (int i=0;i<9;i++)
		{
			for (int j=0;j<9;j++)
			{
				if (board[i][j]=='.')
				{
					expValueSet.clear();
					expValueSet = exceptValueSet(board,i,j);
					for (char c='1';c<='9';c++)//possible char
					{
						//cout<<" i is "<<i<<" j is "<<j<<" char is "<<c<<endl;
						if(expValueSet.find(c)==expValueSet.end())
						{
							if (testUnique(board,i,j,c))
							{
								//cout<<" in  test Unique "<<endl;
								board[i][j] = c;
								flag = true;
							}
						}
					}
				}
			}
		}
	}
}

bool isValid(vector<vector<char> > &board, int a, int b) {
	int i,j;
	for(i = 0; i < 9; i++)
		if(i != a && board[i][b] == board[a][b])
			return false;

	for(j = 0; j < 9; j++)
		if(j != b && board[a][j] == board[a][b])
			return false;

	int x = a/3*3;
	int y = b/3*3;
	for(i = 0; i < 3; i++)
		for(j = 0; j< 3; j++)
			if(x+i != a && y+j != b && board[x+i][y+j] == board[a][b])
				return false;
	return true;
}

bool solveSudokudfs(vector<vector<char> > &board)
{
	for(int i = 0; i < 9; i++)
		for(int j = 0; j < 9; j++)
		{
			if(board[i][j] == '.')
			{
				for(int k = 1; k <= 9; k++)
				{
					board[i][j] = '0' + k;
					if(isValid(board,i,j) && solveSudokudfs(board))
						return true;
					board[i][j] = '.';//this is necessary to recovery the board to the last recursive 
				}
				return false;
			}
		}
		return true;
}


void solveSudoku2(vector<vector<char> > &board) {
	// Note: The Solution object is instantiated only once.
	solveSudokudfs(board);
}

int _tmain(int argc, _TCHAR* argv[])//test case from http://www.sudokuhints.com/
{
	vector<vector<char> > board;
	vector<char> vec;
	/*vec.push_back('4');vec.push_back('6');vec.push_back('3');vec.push_back('7');vec.push_back('2');vec.push_back('8');vec.push_back('9');vec.push_back('5');vec.push_back('1');
	board.push_back(vec);
	vec.clear();
	vec.push_back('2');vec.push_back('5');vec.push_back('9');vec.push_back('4');vec.push_back('6');vec.push_back('1');vec.push_back('7');vec.push_back('3');vec.push_back('8');
	board.push_back(vec);
	vec.clear();
	vec.push_back('7');vec.push_back('8');vec.push_back('1');vec.push_back('3');vec.push_back('5');vec.push_back('9');vec.push_back('6');vec.push_back('4');vec.push_back('2');
	board.push_back(vec);
	vec.clear();
	vec.push_back('5');vec.push_back('3');vec.push_back('2');vec.push_back('1');vec.push_back('9');vec.push_back('7');vec.push_back('4');vec.push_back('8');vec.push_back('6');
	board.push_back(vec);
	vec.clear();
	vec.push_back('9');vec.push_back('1');vec.push_back('4');vec.push_back('6');vec.push_back('8');vec.push_back('2');vec.push_back('5');vec.push_back('7');vec.push_back('3');
	board.push_back(vec);
	vec.clear();
	vec.push_back('6');vec.push_back('7');vec.push_back('8');vec.push_back('5');vec.push_back('4');vec.push_back('3');vec.push_back('1');vec.push_back('2');vec.push_back('9');
	board.push_back(vec);
	vec.clear();
	vec.push_back('8');vec.push_back('2');vec.push_back('6');vec.push_back('9');vec.push_back('7');vec.push_back('5');vec.push_back('3');vec.push_back('1');vec.push_back('4');
	board.push_back(vec);
	vec.clear();
	vec.push_back('1');vec.push_back('4');vec.push_back('7');vec.push_back('2');vec.push_back('3');vec.push_back('6');vec.push_back('8');vec.push_back('9');vec.push_back('5');
	board.push_back(vec);
	vec.clear();
	vec.push_back('3');vec.push_back('9');vec.push_back('5');vec.push_back('8');vec.push_back('1');vec.push_back('4');vec.push_back('2');vec.push_back('6');vec.push_back('7');
	board.push_back(vec);
	vec.clear();*/
	//////////////////////////////////////////////////////////////////////////
	
	/*vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('6');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('.');
	board.push_back(vec);
	vec.clear();
	vec.push_back('.');vec.push_back('8');vec.push_back('.');vec.push_back('3');vec.push_back('.');vec.push_back('2');vec.push_back('.');vec.push_back('4');vec.push_back('.');
	board.push_back(vec);
	vec.clear();
	vec.push_back('.');vec.push_back('.');vec.push_back('5');vec.push_back('.');vec.push_back('4');vec.push_back('.');vec.push_back('9');vec.push_back('.');vec.push_back('.');
	board.push_back(vec);
	vec.clear();
	vec.push_back('.');vec.push_back('7');vec.push_back('.');vec.push_back('4');vec.push_back('.');vec.push_back('5');vec.push_back('.');vec.push_back('8');vec.push_back('.');
	board.push_back(vec);
	vec.clear();
	vec.push_back('8');vec.push_back('.');vec.push_back('4');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('7');vec.push_back('.');vec.push_back('1');
	board.push_back(vec);
	vec.clear();
	vec.push_back('.');vec.push_back('1');vec.push_back('.');vec.push_back('8');vec.push_back('.');vec.push_back('6');vec.push_back('.');vec.push_back('3');vec.push_back('.');
	board.push_back(vec);
	vec.clear();
	vec.push_back('.');vec.push_back('.');vec.push_back('7');vec.push_back('.');vec.push_back('3');vec.push_back('.');vec.push_back('6');vec.push_back('.');vec.push_back('.');
	board.push_back(vec);
	vec.clear();
	vec.push_back('.');vec.push_back('5');vec.push_back('.');vec.push_back('1');vec.push_back('.');vec.push_back('9');vec.push_back('.');vec.push_back('7');vec.push_back('.');
	board.push_back(vec);
	vec.clear();
	vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('8');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('.');
	board.push_back(vec);
	vec.clear();*/

	vec.push_back('.');vec.push_back('.');vec.push_back('9');vec.push_back('7');vec.push_back('4');vec.push_back('8');vec.push_back('.');vec.push_back('.');vec.push_back('.');
	board.push_back(vec);
	vec.clear();
	vec.push_back('7');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('.');
	board.push_back(vec);
	vec.clear();
	vec.push_back('.');vec.push_back('2');vec.push_back('.');vec.push_back('1');vec.push_back('.');vec.push_back('9');vec.push_back('.');vec.push_back('.');vec.push_back('.');
	board.push_back(vec);
	vec.clear();
	vec.push_back('.');vec.push_back('.');vec.push_back('7');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('2');vec.push_back('4');vec.push_back('.');
	board.push_back(vec);
	vec.clear();
	vec.push_back('.');vec.push_back('6');vec.push_back('4');vec.push_back('.');vec.push_back('1');vec.push_back('.');vec.push_back('5');vec.push_back('9');vec.push_back('.');
	board.push_back(vec);
	vec.clear();
	vec.push_back('.');vec.push_back('9');vec.push_back('8');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('3');vec.push_back('.');vec.push_back('.');
	board.push_back(vec);
	vec.clear();
	vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('8');vec.push_back('.');vec.push_back('3');vec.push_back('.');vec.push_back('2');vec.push_back('.');
	board.push_back(vec);
	vec.clear();
	vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('6');
	board.push_back(vec);
	vec.clear();
	vec.push_back('.');vec.push_back('.');vec.push_back('.');vec.push_back('2');vec.push_back('7');vec.push_back('5');vec.push_back('9');vec.push_back('.');vec.push_back('.');
	board.push_back(vec);
	vec.clear();


	//["..9748...","7........",".2.1.9...","..7...24.",".64.1.59.",".98...3..","...8.3.2.","........6","...2759.."]
	//////////////////////////////////////////////////////////////////////////
	cout<<isValidSudoku(board)<<endl;
	for (int i=0;i<9;i++)
	{
		for (int j=0;j<9;j++)
		{
			cout<<board[i][j]<<" ";
		}
		cout<<endl;
	}
	cout<<"after solveSudoku1"<<endl;
	solveSudoku1(board);
	for (int i=0;i<9;i++)
	{
		for (int j=0;j<9;j++)
		{
			cout<<board[i][j]<<" ";
		}
		cout<<endl;
	}
	cout<<"after solveSudoku2"<<endl;
	solveSudoku2(board);
	for (int i=0;i<9;i++)
	{
		for (int j=0;j<9;j++)
		{
			cout<<board[i][j]<<" ";
		}
		cout<<endl;
	}
	system("pause");
	return 0;
}


原文地址:https://www.cnblogs.com/riasky/p/3481907.html