版权声明: https://blog.csdn.net/moon_sky1999/article/details/81667908
题目来源:http://poj.org/problem?id=2918 http://poj.org/problem?id=2676
剪枝+位运算。
优化策略:每行每列按照已填好的数量进行排序,优先填已经填过的多的,这样可以减少搜索的宽度。
代码:
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;
int a[10][10], numl[10], numh[10], h[10], l[10], rh[10], rl[10], b[3][3], tot;
const int cmp1(const int i, const int j) { return numh[i] > numh[j]; }
const int cmp2(const int i, const int j) { return numl[i] > numl[j]; }
bool dfs(int x,int y) {
// cout << tot << endl;
if (tot == 81) {
for (int i = 1; i <= 9; ++i) {
for (int j = 1; j <= 9; ++j) {
cout << a[i][j];
}
cout << endl;
}
return 1;
}
for (int i = x, j = y; i <= 9; ++i, j = 1) {
for (; j <= 9; ++j) {
if (a[rh[i]][rl[j]] == 0) {
int pos = ((h[rh[i]] | l[rl[j]]) | b[(rh[i] - 1) / 3][(rl[j] - 1) / 3]);
if (pos == 511)return 0;
for (int k = 1; k <= 9; ++k) {
if (((1 << (k - 1)) & pos) == 0) {
tot++;
a[rh[i]][rl[j]] = k;
h[rh[i]] |= (1 << (k - 1));
l[rl[j]] |= (1 << (k - 1));
b[(rh[i] - 1) / 3][(rl[j] - 1) / 3] |= (1 << (k - 1));
if (dfs(i, j))return 1;
tot--;
a[rh[i]][rl[j]] = 0;
h[rh[i]] -= (1 << (k - 1));
l[rl[j]] -= (1 << (k - 1));
b[(rh[i] - 1) / 3][(rl[j] - 1) / 3] -= (1 << (k - 1));
}
}
return 0;
}
}
}
return 0;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int _;
cin >> _;
for (int sce = 1; sce <= _; ++sce) {
char c;
memset(a, 0, sizeof(a));
memset(h, 0, sizeof(h));
memset(l, 0, sizeof(l));
memset(b,0,sizeof(b));
memset(numh, 0, sizeof(numh));
memset(numl, 0, sizeof(numl));
tot = 0;
for (int i = 1; i <= 9; ++i) {
for (int j = 1; j <= 9; ++j) {
cin >> c;
a[i][j] = c - '0';
if (a[i][j] != 0) {
tot++;
h[i] |= (1 << (a[i][j] - 1));
numh[i]++;
l[j] |= (1 << (a[i][j] - 1));
numl[j]++;
b[(i - 1) / 3][(j - 1) / 3] |= (1 << (a[i][j] - 1));
}
}
rl[i] = i;
rh[i] = i;
}
sort(rl + 1, rl + 10, cmp2);
sort(rh + 1, rh + 10, cmp1);
// cout << "Scenario #" << sce << ":" << endl;
dfs(1, 1);
cout << endl;
}
return 0;
}