LeetCode 37 Sudoku Solver

来源:互联网 发布:淘宝囤货节在哪 编辑:程序博客网 时间:2024/05/21 01:55

题意:

给出一个一定有解的填了一部分的数独,要求填满它。


思路:

我是分2步解决这个问题的:

第1步检查每个格子可能填哪几个数字,第2步dfs搜索结果。

dfs的时候只搜索第1步中找出的可能的数字,每次尝试填入一个格子并更新当前行、当前列、当前3*3格子的可选数字,注意回溯。

我的代码3ms就可以跑完,效率还是很不错的。


代码:

class Solution {public:    void solveSudoku(vector<vector<char>> &board) {        can.clear();        int besti = 0, bestj = 0, bestcnt = 10;        for (int i = 0; i < n; ++i) {            vector<set<int>> tmp;            for (int j = 0; j < n; ++j) {                if (board[i][j] != '.') {                    tmp.push_back(set<int> {});                    continue;                }                set<int> now = candidate(i, j, board);                int cnt = now.size();                // if(cnt == 1){                //     board[i][j] = *(now.begin()) + '1';                //     tmp.push_back(set<int>{});                //     continue;                // }                tmp.push_back(now);                if (cnt < bestcnt) {                    besti = i;                    bestj = j;                    bestcnt = cnt;                }            }            can.push_back(tmp);        }        if (bestcnt != 10) {            if (dfs(besti, bestj, board)) {                printf("success!");            } else {                printf("fuck!");            }        }    }private:    int n = 9;    vector<vector<set<int>>> can;    set<int> candidate(int i, int j, vector<vector<char>> &board) {        bool app[9];        memset(app, false, sizeof(app));        for (int k = 0; k < n; ++k) {            if (board[i][k] != '.') {                app[board[i][k] - '1'] = true;            }            if (board[k][j] != '.') {                app[board[k][j] - '1'] = true;            }            int di = i / 3 * 3 + k / 3, dj = j / 3 * 3 + k % 3;            if (board[di][dj] != '.') {                app[board[di][dj] - '1'] = true;            }        }        set<int> res;        for (int k = 0; k < n; ++k) {            if (!app[k]) {                res.insert(k);            }        }        return res;    }    bool dfs(int x, int y, vector<vector<char>> &board) {        stack<pair<int, int>> effect;        set<int> now = can[x][y];        can[x][y].clear();        for (int k : now) {            // printf("%d %d %d\n", x + 1, y + 1, k + 1);            board[x][y] = k + '1';            for (int i = 0; i < n; ++i) {                if (i != y && can[x][i].find(k) != can[x][i].end()) {                    can[x][i].erase(k);                    effect.push(make_pair(x, i));                }                if (i != x && can[i][y].find(k) != can[i][y].end()) {                    can[i][y].erase(k);                    effect.push(make_pair(i, y));                }                int di = x / 3 * 3 + i / 3, dj = y / 3 * 3 + i % 3;                if (can[di][dj].find(k) != can[di][dj].end()) {                    can[di][dj].erase(k);                    effect.push(make_pair(di, dj));                }            }            int besti = 0, bestj = 0, bestcnt = 10;            for (int i = 0; i < n; ++i) {                for (int j = 0; j < n; ++j) {                    if (board[i][j] == '.' && can[i][j].size() < bestcnt) {                        besti = i;                        bestj = j;                        bestcnt = can[i][j].size();                    }                }            }            if (bestcnt != 0) {                if (bestcnt == 10 || dfs(besti, bestj, board)) {                    return true;                }            }            while (!effect.empty()) {                pair<int, int> e = effect.top();                effect.pop();                can[e.first][e.second].insert(k);            }        }        board[x][y] = '.';        can[x][y] = now;        return false;    }};


原创粉丝点击