AcWing 166. 数独
原题链接
中等
作者:
皓首不倦
,
2020-08-04 13:00:45
,
所有人可见
,
阅读 466
#include <stdio.h>
#include <string.h>
#include <map>
using namespace std;
int line_mask[9];
int col_mask[9];
int block_mask[3][3];
int one_cnt[(1 << 9) - 1];
map<int, int> bitval2trueval;
int get_one_cnt(int val) {
int ans = 0;
while (val) {
ans += 1;
val &= (val - 1);
}
return ans;
}
bool dfs(int cnt, int max_cnt, char* s) {
if (cnt == max_cnt) {
printf("%s\n", s);
return true;
}
// 选择分支最少的元素
int mask = 0, cur_one_cnt = 0;
int min_one_cnt = 0x7fffffff;
int best_i = -1, best_j = -1, best_mask = -1;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (s[i*9+j] != '.') {
continue;
}
mask = line_mask[i] & col_mask[j] & block_mask[i/3][j/3];
cur_one_cnt = one_cnt[mask >> 1];
if (cur_one_cnt < min_one_cnt) {
min_one_cnt = cur_one_cnt;
best_i = i;
best_j = j;
best_mask = mask;
}
}
}
int bit_val;
while (best_mask) {
bit_val = best_mask & (-best_mask);
best_mask &= (best_mask - 1);
s[best_i * 9 + best_j] = '0' + bitval2trueval[bit_val];
line_mask[best_i] &= ~bit_val;
col_mask[best_j] &= ~bit_val;
block_mask[best_i/3][best_j/3] &= ~bit_val;
if (dfs(cnt+1, max_cnt, s)) {
return true;
}
s[best_i * 9 + best_j] = '.';
block_mask[best_i/3][best_j/3] |= bit_val;
col_mask[best_j] |= bit_val;
line_mask[best_i] |= bit_val;
}
return false;
}
int main(void) {
freopen("/Users/grh/Programming/CLionProjects/Test/data.txt", "r", stdin);
char s[200];
// 提前先把one_cnt计算出来
for (int val = 0; val < (1<<9); val++) {
one_cnt[val] = get_one_cnt(val);
}
for (int i = 1; i < 10; i++) {
bitval2trueval[1 << i] = i;
}
while (true) {
scanf("%s", s);
if (strcmp(s, "end") == 0) {
break;
}
for (int i = 0; i < 9; i++) {
line_mask[i] = (1 << 10) - 2;
col_mask[i] = (1 << 10) - 2;
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j <3; j++) {
block_mask[i][j] = (1 << 10) - 2;
}
}
int idx = 0, val = 0, emp_cnt = 0;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
idx = i*9 + j;
if (s[idx] != '.') {
val = s[idx] - '0';
line_mask[i] &= ~(1<<val);
col_mask[j] &= ~(1<<val);
block_mask[i/3][j/3] &= ~(1<<val);
} else {
emp_cnt += 1;
}
}
}
dfs(0, emp_cnt, s);
}
return 0;
}