问题描述:
Write a program to solve a Sudoku puzzle by filling the empty cells.
A sudoku solution must satisfy all of the following rules:
Each of the digits 1-9 must occur exactly once in each row.
Each of the digits 1-9 must occur exactly once in each column.
Each of the the digits 1-9 must occur exactly once in each of the 9 3x3 sub-boxes of the grid.
Empty cells are indicated by the character ‘.’.
A sudoku puzzle…
…and its solution numbers marked in red.
Note:
The given board contain only digits 1-9 and the character ‘.’.
You may assume that the given Sudoku puzzle will have a single unique solution.
The given board size is always 9x9.
题源:here;完整实现:here
思路:
自己写一个程序解数独问题!挺有意思。首先我们使用三个矩阵来记录数独中的约束:
vector<vector<bool>> areaMap;
vector<vector<bool>> rowMap;
vector<vector<bool>> colMap;
areaMap:记录3×3的子矩阵中哪些数被占据
rowMap:记录每一行中哪些数被占据
colMap:记录每一列中哪些数被占据
如果某个数在以上三个位置都不存在,则是可能被填上的数,我们的程序就是不断的尝试那些可能被填上的数,当然是通过递归的方式。
为了方便记录填补的位置,我们使用一个变量fillNum
来表征在填补第几个位置,当然需要将其转换为行列数,当fillNum >= 81
时我们认为数独游戏完成。
最后贴出完整实现:
class Solution {
public:
vector<vector<bool>> areaMap;
vector<vector<bool>> rowMap;
vector<vector<bool>> colMap;
bool initMaps(vector<vector<char>> board){
areaMap = vector<vector<bool>>(9, vector<bool>(9, false));
rowMap = vector<vector<bool>>(9, vector<bool>(9, false));
colMap = vector<vector<bool>>(9, vector<bool>(9, false));
for (int i = 0; i < 9; i++){
for (int j = 0; j < 9; j++){
if (board[i][j] == '.') continue;
int digit = board[i][j] - '1';
int areaIdx = i / 3 + j / 3 * 3;
if (areaMap[areaIdx][digit] || rowMap[i][digit] || colMap[j][digit]) return false;
areaMap[areaIdx][digit] = rowMap[i][digit] = colMap[j][digit] = true;
}
}
return true;
}
bool fillBoard(vector<vector<char>>& board, int fillNum){
if (fillNum >= 81) return true;
int rowFill = fillNum / 9;
int colFill = fillNum % 9;
if (board[rowFill][colFill] != '.') return fillBoard(board, fillNum + 1);
for (int i = 0; i < 9; i++){
int areaIdx = rowFill / 3 + colFill / 3 * 3;
int digit = i;
if (areaMap[areaIdx][digit] || rowMap[rowFill][digit] || colMap[colFill][digit]) continue;
board[rowFill][colFill] = '1'+i;
areaMap[areaIdx][digit] = rowMap[rowFill][digit] = colMap[colFill][digit] = true;
if (fillBoard(board, fillNum + 1)) return true;
board[rowFill][colFill] = '.';
areaMap[areaIdx][digit] = rowMap[rowFill][digit] = colMap[colFill][digit] = false;
}
return false;
}
void solveSudoku(vector<vector<char>>& board) {
if (!initMaps(board)) return;
bool result = fillBoard(board, 0);
}
};