[バックトラッキング] [leetcode]数独を解く

トピック:

数独を解く

ソース:

37.数独を解く

問題解決のアイデア:バックトラック

まず、すべての空の位置を見つけ、各空の位置を順番に選択し、行、列、および現在のセルに従って設定された候補番号を選択します。セット内の各番号の再帰+バックトラック。

  • 再帰的終了条件:すべての空の位置が埋められます

ここでの関数にはbool戻り値があり、直接戻りに便利です。解決策を見つける前に、各番号とバックトラックを繰り返します。解決策が見つかると、すぐに戻り、バックトラックを実行できません。戻ると、埋められた位置がクリアされます。

class Solution {
public:
    void solveSudoku(vector<vector<char>>& board) {
        vector<int> space;
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                if (board[i][j] == '.') {
                    space.push_back(i * 10 + j);
                }
            }
        }
        back(board, space, 0);
    }
    bool back(vector<vector<char>>& board, const vector<int>& space, int start) {
        if (start == space.size()) {
            return true;
        }
        int t = space[start];
        int x = t / 10; // x行
        int y = t % 10; // y列
        for (int i = 0; i < 9; i++) {
            char v = i+1+'0';
            if (check(board, x, y, v)) {
                board[x][y] = v;
                if (back(board, space, start+1)) return true;
                board[x][y] = '.'; // 找到以后不能再回溯,所以函数直接返回不能到达这里
            }
        }
        return false;
    }
    bool check(const vector<vector<char>>& board, int x, int y, char v) {
        // 第x行
        for (int i = 0; i < 9; i++) {
            if (board[x][i] == v) return false;
        }
        // 第y列
        for (int i = 0; i < 9; i++) {
            if (board[i][y] == v) return false;
        }
        // 当前单元格
        int row = x / 3 * 3;
        int col = y / 3 * 3;
        for (int r = row; r < row+3; r++) {
            for (int c = col; c < col+3; c++) {
                if (board[r][c] == v) return false;
            }
        }
        return true;
    }
};

 

おすすめ

転載: blog.csdn.net/hbuxiaoshe/article/details/115311517