编写一个程序,通过填充空格来解决数独问题。
数独的解法需 遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
数独部分空格内已填入了数字,空白格用 ‘.’ 表示。
输入:board = [[“5”,“3”,“.”,“.”,“7”,“.”,“.”,“.”,“.”],[“6”,“.”,“.”,“1”,“9”,“5”,“.”,“.”,“.”],[“.”,“9”,“8”,“.”,“.”,“.”,“.”,“6”,“.”],[“8”,“.”,“.”,“.”,“6”,“.”,“.”,“.”,“3”],[“4”,“.”,“.”,“8”,“.”,“3”,“.”,“.”,“1”],[“7”,“.”,“.”,“.”,“2”,“.”,“.”,“.”,“6”],[“.”,“6”,“.”,“.”,“.”,“.”,“2”,“8”,“.”],[“.”,“.”,“.”,“4”,“1”,“9”,“.”,“.”,“5”],[“.”,“.”,“.”,“.”,“8”,“.”,“.”,“7”,“9”]]
输出:[[“5”,“3”,“4”,“6”,“7”,“8”,“9”,“1”,“2”],[“6”,“7”,“2”,“1”,“9”,“5”,“3”,“4”,“8”],[“1”,“9”,“8”,“3”,“4”,“2”,“5”,“6”,“7”],[“8”,“5”,“9”,“7”,“6”,“1”,“4”,“2”,“3”],[“4”,“2”,“6”,“8”,“5”,“3”,“7”,“9”,“1”],[“7”,“1”,“3”,“9”,“2”,“4”,“8”,“5”,“6”],[“9”,“6”,“1”,“5”,“3”,“7”,“2”,“8”,“4”],[“2”,“8”,“7”,“4”,“1”,“9”,“6”,“3”,“5”],[“3”,“4”,“5”,“2”,“8”,“6”,“1”,“7”,“9”]]
解释:输入的数独如上图所示,唯一有效的解决方案如下所示:
提示:
board.length == 9
board[i].length == 9
board[i][j] 是一位数字或者 ‘.’
题目数据 保证 输入数独仅有一个解
代码:
class Solution {
public:
//查询在(x,y)位置有可能放的数字
bitset<9> get_pos_num(int x,int y)
{
return ~(rows[x] | lines[y] | cells[x / 3][y / 3]);
}
//在所有未选择的数字中,选择一个可能情况最小的数字进行确定
vector<int> get_num(vector<vector<char>>& board)
{
vector<int> ve;
int mins = 1e9;
for(int i = 0;i < board.size();i ++)
{
for(int j = 0;j < board[i].size();j ++)
{
if(board[i][j] != '.') continue;
auto bit = get_pos_num(i,j);
if(bit.count() >= mins) continue;
ve = {i,j};
mins = bit.count();
}
}
return ve;
}
bool dfs(vector<vector<char>>& board,int cnt)
{
if(cnt == 0) return true;
//求得下一个最小步数的x,y位置
auto next = get_num(board);
int x = next[0],y = next[1];
//获得可能要取的数字
auto pos_num = get_pos_num(x,y);
for(int i = 0;i < board[x].size();i ++)
{
if(!pos_num.test(i)) continue;
board[x][y] = char(i + '1');
rows[x] |= (1 << i);
lines[y] |= (1 << i);
cells[x / 3][y / 3] |= (1 << i);
if(dfs(board,cnt - 1)) return true;
board[x][y] = '.';
rows[x] ^= (1 << i);
lines[y] ^= (1 << i);
cells[x / 3][y / 3] ^= (1 << i);
}
return false;
}
void solveSudoku(vector<vector<char>>& board) {
rows = vector<bitset<9>>(9,bitset<9>());
lines = vector<bitset<9>>(9,bitset<9>());
cells = vector<vector<bitset<9>>>(3,vector<bitset<9>>(3,bitset<9>()));
int cnt = 0;
for(int i = 0;i < board.size();i ++)
{
for(int j = 0;j < board[i].size();j ++)
{
if(board[i][j] == '.')
{
cnt ++;
continue;
}
int x = board[i][j] - '1';
rows[i] |= (1 << x);
lines[j] |= (1 << x);
cells[i / 3][j / 3] |= (1 << x);
}
}
dfs(board,cnt);
}
private:
//每行的(0,0,0,0,0,0,0,0,0)
vector<bitset<9>> rows;
//标记每列的
vector<bitset<9>> lines;
//标记每(3*3)的单元格
vector<vector<bitset<9>>> cells;
};