首先了解什么是sudoku,见http://sudoku.com.au/TheRules.aspx
即在9X9棋盘里,每一行都要包括1-9数字,每个数字只能出现一次不能重复;每一列都要包括1-9数字,每个数字只能出现一次不能重复;每个3x3小宫格要包括1-9数字,每个数字只能出现一次不能重复。
36. Valid Sudoku
主要是对已有的一个9X9棋盘(部分填充数字,没有数字的单元格有‘.’填充),判断是否满足sudoku定义:即对每一行。每一列和每个小宫格看有没有重复的,对于行和列的判断很简单,关键在于小宫格的判断:
对于给定9X9棋盘,规定坐标:
0 1 2 3 4 5 6 7 8
行号规律:
第0个九宫格:000111222; 第1个九宫格:000111222; 第2个九宫格:000111222;
第3个九宫格:333444555; 第4个九宫格:333444555; 第5个九宫格:333444555;
第6个九宫格:666777888; 第7个九宫格:666777888; 第8个九宫格:666777888;
列号规律:第0个九宫格:012012012; 第1个九宫格:345345345; 第2个九宫格:678678678;
第3个九宫格:012012012; 第4个九宫格:345345345; 第5个九宫格:678678678;
第6个九宫格:012012012; 第7个九宫格:345345345; 第8个九宫格:678678678;
则 第 i 个九宫格里面的第 j 个元素在原矩阵的第 3*(i/3) + j/3 行,第 3*(i%3) + j%3)列,(i和j从0开始)bool isValidSudoku(vector<vector<char>>& board){
int i,j;
for(i=0;i<9;i++){
map<char,bool>m1;
map<char,bool>m2;
map<char,bool>m3;
for(j=0;j<9;j++){
if(board[i][j]!='.'){if(m1[board[i][j]]==true)return false;
m1[board[i][j]]=true;//第一次出现
}
if(board[j][i]!='.'){if(m2[board[j][i]]==true)return false;
m2[board[j][i]]=true;
}
if(board[i/3*3+j/3][i%3*3+j%3]!='.'){if(m3[board[i/3*3+j/3][i%3*3+j%3]]==true)return false;
m3[board[i/3*3+j/3][i%3*3+j%3]]=true;
}
}
}
return true;
}
37. Sudoku Solver
对部分填充的sudoku填完,使成为一个sudoku。
类似N-Queen问题,采用回溯法,
需要注意的区别是:
本题找到解的处理是return true,因此返回值为bool
N-Queen找到解的处理是保存解,因此返回值为void
对于每个空位'.',遍历1~9,check合理之后往下一个位置递归。由于这里路径尝试本质上是有序的,即1~9逐个尝试,因此无需额外设置状态位记录已经尝试过的方向,如果该空格无论设置什么数字都无法达到合法状态,那么回溯重新设置上一个空格。bool checkValidSudoku(vector< vector<char> >& board,int i,int j){
for(int k=0;k<9;k++)
if(k!=j&&board[i][k]==board[i][j])return false;
for(int k=0;k<9;k++)
if(k!=i&&board[k][j]==board[i][j])return false;
for(int row=i/3*3;row<i/3*3+3;row++)
{
for(int col=j/3*3;col<j/3*3+3;col++)
if((row!=i||col!=j)&&board[row][col]==board[i][j])return false;
}//i,j所在grid的其他坐标位置,不同于36题
return true;
}
bool helper_sudoku(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]=k+'0';
if(checkValidSudoku(board,i,j)&&helper_sudoku(board))return 1;
board[i][j]='.';
}
return 0;
}
return 1;
}
void solveSudoku(vector< vector<char> > &board){
helper_sudoku(board);
}