题目地址
题意:给你一个n,然后给你一个n^2阶的数独,n分别有2,3,4这3种情况,然后你判断这个数独是不是有唯一的一个解,如果没有解的话输出”No Solution”,多个解的话就是输出”Multiple Solutions”,否则判断这个唯一解是不是最小解(最小解就是把任何一个给定的数变为不确定的话就会有多组解)
思路:我们通过map去映射字符与数字的关系,然后我们在DLX中加一个变量记录有多少种情况,(剪枝:当大于等于2的时候说明一定是有多组解的所以我们在tot等于2的时候直接让他返回就好了,因为已经是多组解了,没有必要继续搜索下去),如果我们只有一组解的话,我们就枚举每一个不为’.’的点,把他置为’.’,再进行一边DLX判断他是不是有多组解,如果有一个没有的就是输出”Not Minimal” ,否则输出数独结果就好了。
PS:这题还是蛮考对数独转DLX精确覆盖的理解的,题目其实不难,只是需要细心。我就是忘记把我测试输出的东西删掉了导致找了一天的bug。
#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <iomanip>
#define N 110
#define MAXSIZE 1010*1010
#define LL __int64
#define inf 0x3f3f3f3f
#define lson l,mid,ans<<1
#define rson mid+1,r,ans<<1|1
#define getMid (l+r)>>1
#define movel ans<<1
#define mover ans<<1|1
using namespace std;
const LL mod = 1000000007;
struct node {
int left, right, up, down, col, row;
}mapp[MAXSIZE];
int S[MAXSIZE], H[MAXSIZE];//S记录该列中1元素的个数
int head, cnt;
int ans[MAXSIZE];
int len;
int tot;
struct Dancing_Links_X {
void init(int m) {
head = 0; tot = 0;
for (int i = 0; i <= m; i++) {
S[i] = 0;
mapp[i].up = mapp[i].down = i;
mapp[i].left = (i == 0 ? m : i - 1);
mapp[i].right = (i == m ? 0 : i + 1);
}
cnt = m;
memset(H, -1, sizeof(H));
}
void link(int x, int y) {
cnt++;
mapp[cnt].row = x;
mapp[cnt].col = y;
S[y]++;
mapp[cnt].up = mapp[y].up;
mapp[cnt].down = y;
mapp[mapp[y].up].down = cnt;
mapp[y].up = cnt;
if (H[x] == -1) H[x] = mapp[cnt].left = mapp[cnt].right = cnt;
else {
mapp[cnt].left = mapp[H[x]].left;
mapp[cnt].right = H[x];
mapp[mapp[H[x]].left].right = cnt;
mapp[H[x]].left = cnt;
}
}
void remove(int c) {//删去c这个点,以及关联的一列
mapp[mapp[c].right].left = mapp[c].left;
mapp[mapp[c].left].right = mapp[c].right;
for (int i = mapp[c].down; i != c; i = mapp[i].down) {
for (int j = mapp[i].right; j != i; j = mapp[j].right) {
mapp[mapp[j].down].up = mapp[j].up; mapp[mapp[j].up].down = mapp[j].down;
--S[mapp[j].col];
}
}
}
void resume(int c) {//恢复c这个点,以及关联的一列
for (int i = mapp[c].up; i != c; i = mapp[i].up) {
for (int j = mapp[i].left; j != i; j = mapp[j].left) {
++S[mapp[j].col];
mapp[mapp[j].down].up = mapp[mapp[j].up].down = j;
}
}
mapp[mapp[c].right].left = mapp[mapp[c].left].right = c;
}
void dance1(int k) {
if (mapp[head].right == head) {
len = k;
tot++;
return;
}
int s = inf, c;
for (int t = mapp[head].right; t != head; t = mapp[t].right) {
if (S[t] < s) s = S[t], c = t;
}
remove(c);
for (int i = mapp[c].down; i != c; i = mapp[i].down) {
ans[k] = mapp[i].row;
for (int j = mapp[i].right; j != i; j = mapp[j].right) {
remove(mapp[j].col);
}
dance1(k + 1);
if (tot == 2) {
return;
}
for (int j = mapp[i].left; j != i; j = mapp[j].left) {
resume(mapp[j].col);
}
}
resume(c);
}
bool dance(int k) {
if (mapp[head].right == head) {
len = k;
//cout << endl << len << endl << endl;
return true;
}
int s = inf, c;
for (int t = mapp[head].right; t != head; t = mapp[t].right) {
if (S[t] < s) s = S[t], c = t;
}
remove(c);
for (int i = mapp[c].down; i != c; i = mapp[i].down) {
ans[k] = mapp[i].row;
for (int j = mapp[i].right; j != i; j = mapp[j].right) {
remove(mapp[j].col);
}
if (dance(k + 1)) {
return true;
}
for (int j = mapp[i].left; j != i; j = mapp[j].left) {
resume(mapp[j].col);
}
}
resume(c);
return false;
}
}DLX;
char mat[N][N];
map<char, int>map1;
map<int, char>map2;
void build(int n, int m) {
DLX.init(m * m * 4);
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
if (mat[i][j] != '.') {
int r = (i * m + j) * m + map1[mat[i][j]];
int c1 = i * m + j + 1;
int c2 = m * m + i * m + map1[mat[i][j]];
int c3 = 2 * m * m + j * m + map1[mat[i][j]];
int c4 = 3 * m * m + (i / n * n + j / n) * m + map1[mat[i][j]];
DLX.link(r, c1);
DLX.link(r, c2);
DLX.link(r, c3);
DLX.link(r, c4);
S[c1] = S[c2] = S[c3] = S[c4] = -1;
}
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
if (mat[i][j] == '.') {
for (int k = 1; k <= m; k++) {
int r = (i * m + j) * m + k;
int c1 = i * m + j + 1;
int c2 = m * m + i * m + k;
int c3 = 2 * m * m + j * m + k;
int c4 = 3 * m * m + (i / n * n + j / n) * m + k;
if (~S[c1] && ~S[c2] && ~S[c3] && ~S[c4]) {
DLX.link(r, c1);
DLX.link(r, c2);
DLX.link(r, c3);
DLX.link(r, c4);
}
}
}
}
}
}
int main() {
cin.sync_with_stdio(false);
int n, m;
map1.clear();
map1['1'] = 1;map1['2'] = 2;map1['3'] = 3;map1['4'] = 4;
map1['5'] = 5;map1['6'] = 6;map1['7'] = 7;map1['8'] = 8;
map1['9'] = 9;map1['A'] = 10;map1['B'] = 11;map1['C'] = 12;
map1['D'] = 13;map1['E'] = 14;map1['F'] = 15;map1['G'] = 16;
map2.clear();
map2[1] = '1';map2[2] = '2';map2[3] = '3';map2[4] = '4';
map2[5] = '5';map2[6] = '6';map2[7] = '7';map2[8] = '8';
map2[9] = '9';map2[10] = 'A';map2[11] = 'B';map2[12] = 'C';
map2[13] = 'D';map2[14] = 'E';map2[15] = 'F';map2[16] = 'G';
while (cin >> n) {
m = n*n;
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
cin >> mat[i][j];
}
}
build(n, m);
len = inf;
DLX.dance1(0);
if (tot == 0) {
cout << "No Solution" << endl;
}
else if (tot == 1) {
bool flag = true;
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
if (mat[i][j] == '.') continue;
char ch = mat[i][j];
mat[i][j] = '.';
build(n, m);
len = inf;
DLX.dance1(0);
if (tot != 2) {
flag = false;
break;
}
mat[i][j] = ch;
}
}
if (!flag) {
cout << "Not Minimal" << endl;
}
else {
build(n, m);
len = inf;
DLX.dance(0);
for (int i = 0; i < len; i++) {
int Orz = (ans[i] - 1) % m + 1;
int x = (ans[i] - 1) / m / m;
int y = (ans[i] - 1) / m % m;
if (mat[x][y] != '.') continue;
mat[x][y] = map2[Orz];
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
cout << mat[i][j];
}
cout << endl;
}
}
}
else {
cout << "Multiple Solutions" << endl;
}
}
return 0;
}