编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 ‘.’ 表示。
一个数独。
答案被标成红色。
Note:
给定的数独序列只包含数字 1-9 和字符 ‘.’ 。
你可以假设给定的数独只有唯一解。
给定数独永远是 9x9 形式的。
解析:这一题在上一题的基础上,要求求解数独。
对于这一些问题,计算机大多采用回溯法解决问题,即尝试每一种可行的尝试,直至尝试失败,则将做出的修改回溯至未修改,然后尝试下一种。
class Solution {
public:
void solveSudoku(vector<vector<char>>& board) {
rol.resize(9);
col.resize(9);
box.resize(9);
//初始化数组
for(int i=0;i<9;++i)
for(int j=0;j<9;++j)
if(board[i][j]!='.'){
int n = board[i][j]-'0';
rol[i][n]=col[j][n]=box[i/3*3+j/3][n]=1;
}
//调用回溯方法填充数组
fillone(board,0,0);
}
private:
vector<bitset<9>> rol;
vector<bitset<9>> col;
vector<bitset<9>> box;
bool res=false;
void fillone(vector<vector<char>>& board,int r,int c){
if(board[r][c]=='.'){
//对每一个格子尝试所有9个数字
for(int i=1;i<10;++i){
if(rol[r][i]==0&&col[c][i]==0&&box[r/3*3+c/3][i]==0){
rol[r][i]=col[c][i]=box[r/3*3+c/3][i]=1;
board[r][c]=i+'0';
//最后一个格子填充,数独解开
if(r==8&&c==8) res=true;
else{ //假设当前格子正确,继续下一个格子的填充
if(c==8) fillone(board,r+1,0);
else fillone(board,r,c+1);
}
if(!res){ //经验证当前格子填充错误,将格子回溯至未填充状态。
rol[r][i]=col[c][i]=box[r/3*3+c/3][i]=0;
board[r][c]='.';
}
}
}
}
//如果已经有预先设好的数字,直接判断填充下一个
else{
if(r==8&&c==8) res=true;
else{
if(c==8) fillone(board,r+1,0);
else fillone(board,r,c+1);
}
}
}
};