题目简介
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…
题目分析
这道题目虽然是hard,但是算法角度来看这道题一点都不难。首先我是先做了一个easy的相关题目练手,顺带把有关这题的函数写了。也就是判断一个数独是否有效(含有空格的形况下),也就是对每行,每个九宫格,每列,进行检查有没有重复使用的数字,时间复杂度为O(N^2),看起来这个复杂度很可怕,但其实因为N非常小,几乎可以看成是常数级地运算。
算法分析
这道题一看就是用DFS的穷搜的方法,每个待定数字一个一个搜索,出现死路则回溯,时间复杂度看起来也是十分可怕O(N^N),但是实际上,由于N很小,以及在DFS期间剪掉了很多枝,所以在运行时间上来看,还是十分有效的。已经,这里在check上面可以有个小改进,实际上对新加入来的数字,只需要检验其所在的行、列和九宫格是否有效就可以了,不必对整个数独进行检验,在检验上的时间复杂度可以减少一个数量级,但是由于N很小,我就没有改了。
void print(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;
}
void initial_used(bool * used){
for(int i = 0 ; i < 9 ; i ++)
used[i] =false;
}
bool isValidSudoku(vector<vector<char> >& board) {
bool *used = new bool [9];
// check row
for (int i =0 ; i < 9 ;i++){
initial_used(used);
for(int j = 0 ; j < 9 ; j++){
if(board[i][j]!='.')
{
//cout<<board[i][j]-'0'<<endl;
if(used[board[i][j]-'1']) return false;
used[board[i][j]-'1'] =true;
}
}
}
//check col
for (int j =0 ; j < 9 ;j++){
initial_used(used);
for(int i = 0 ; i < 9 ; i++){
if(board[i][j]!='.')
{
if(used[board[i][j]-'1']) return false;
used[board[i][j]-'1'] =true;
} }
}
// check grid
int beg[9][2] = {{0,0},{0,3},{0,6},{3,0},{3,3},{3,6},{6,0},{6,3},{6,6}};
for(int k = 0 ; k < 9 ; k++ ){
int x = beg[k][0];
int y = beg[k][1];
initial_used(used);
for(int i = 0 ;i<3;i++){
for(int j = 0 ;j<3 ;j++){
if(board[x+i][y+j]!='.')
{
if(used[board[x+i][y+j]-'1']) return false;
used[board[x+i][y+j]-'1'] =true;
}
}
}
}
delete[] used;
return true;
}
void solve(vector<vector<char> >& board , int x , int y ,bool &yes){
if(y==9){
y= 0 ;x++;
}
if(x==9){
yes = true;
return ;
}
while(board[x][y]!='.'){
y++;
if(y==9){
y= 0 ;x++;
}
if(x==9){
yes = true;
return ;
}
}
//cout<<count++<<endl;
//print(board);
for(int letter = 0 ; letter< 9 ; letter ++){
board[x][y]=letter+'1';
if(isValidSudoku(board)){
solve(board,x,y+1,yes);
if(yes) return ;
}
}
board[x][y] = '.';
}
void solveSudoku(vector<vector<char> > & board) {
bool yes = false;
int x , y;
for(int i = 0 ; i< 9 ;i++)
for(int j = 0 ; j < 9;j++)
if(board[i][j]=='.'){
x = i;
y= j;
goto solve_pro;
}
solve_pro:
solve(board,x,y,yes);
}