您的位置:首页 > 其它

LeetCode 37 Sudoku Solver

2017-05-24 14:49 274 查看
题意:

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

思路:

我是分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;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: