voidSolution::init() { // update map[][], choosenNum[][], q q.reserve(SIZE * SIZE); // 预分配空间 for (int i = 0; i < SIZE; ++i) { for (int j = 0; j < SIZE; ++j) { if (map[i][j] == 0) { // 是需要填充的情况 q.push_back(make_pair(i, j)); // 加入待填充队列 } else { // 是已填充的情况,更新choosenNum[][] for (int k = 0; k < SIZE; ++k) { choosenNum[i][k] |= NUMBERS[map[i][j]]; // row choosenNum[k][j] |= NUMBERS[map[i][j]]; // column int boxRow = i / 3, boxCol = j / 3; int ii = boxRow * 3 + k / 3, jj = boxCol * 3 + k % 3; choosenNum[ii][jj] |= NUMBERS[map[i][j]]; // box } } } } // update originChoosen[][] for (int i = 0; i < SIZE; ++i) { for (int j = 0; j < SIZE; ++j) { originChoosen[i][j] = choosenNum[i][j]; } } }
boolSolution::check(int row, int col, int num) { // check row for (int i = 0; i < SIZE; ++i) { if (i != col && map[row][i] == num) returnfalse; } // check column for (int i = 0; i < SIZE; ++i) { if (i != row && map[i][col] == num) returnfalse; } // check box int boxRow = row / 3, boxCol = col / 3; for (int i = 0; i < SIZE; ++i) { int ii = boxRow * 3 + i / 3, jj = boxCol * 3 + i % 3; if ((ii != row || jj != col) && map[ii][jj] == num) returnfalse; } map[row][col] = num; returntrue; }
voidSolution::inputBoard(std::vector<std::vector<char>>& board) { for (int i = 0; i < SIZE; ++i) { for (int j = 0; j < SIZE; ++j) { if (board[i][j] >= '1' && board[i][j] <= '9') map[i][j] = board[i][j] - '0'; else map[i][j] = 0; } } }
voidSolution::inputBoard(std::vector<std::vector<int>>& board){ for (int i = 0; i < SIZE; ++i) { for (int j = 0; j < SIZE; ++j) { map[i][j] = board[i][j]; } } }
voidSolution::solveSudoku() { init(); for (auto it = q.begin(); it != q.end(); ) { int row = it->first, col = it->second; if (map[row][col] == 0 && choosenNum[row][col] == NUMBERS[0]) { choosenNum[row][col] = originChoosen[row][col]; // 重置可选数字 --it; continue; // 没有可以填充的数字,直接跳过,在下一轮循环重新填充上一个空格 }
map[row][col] = 0; // 先将该位置置为0,防止重新填充失败时下面判断错误 // 尝试填充所有可能的数字 NUMBERS[i] for (int i = 1; i <= SIZE; ++i) { if (choosenNum[row][col] & NUMBERS[i]) { // 该数字不可能填充 continue; } choosenNum[row][col] |= NUMBERS[i]; if (check(row, col, i)) { // 该数字可以填充 break; // 进入外层的下一轮循环 } } if (map[row][col] != 0) { // 该位置填充了数字 ++it; } } }
voidSolution::printBoard() { for (int i = 0; i < SIZE; ++i) { for (int j = 0; j < SIZE; ++j) { cout << map[i][j] << " \n"[j == SIZE - 1]; } } }