最近在学Dancing links 然后问学长。。。被骂- -
“这么简单都不会啊!!!自己慢慢学。。。什么都要人教的啊。。。那你以后怎么办啊!!!”
好吧~然后。。自学了。。。
自己各种理解后总结的。。。断断续续地花了一个下午。
这个就是以后Dacing links的模板了。。。吼吼吼吼~
<code>
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define INF 1000000000
const int N = 9;
const int head = 0;
const int mn = N * N * N *(N * N * N * 4) + N;
const int nn = N * N * N + N;
int U[mn], D[mn], L[mn], R[mn];
int C[mn], Row[mn];
int H[nn], Q[nn], S[nn], vis[nn], size;
int a[nn][nn], ans[nn][nn];
void prepare(int r, int c) {
int i;
for (i = 0; i <= c; i++) {
S[i] = 0; //当前列元素个数
U[i] = D[i] = i;
R[i] = i + 1;
L[i + 1] = i;
}
R[c] = 0;
size = c;
while (r) {
H[r--] = -1;
}
}
void place(int &r, int &c1, int &c2, int &c3, int &c4, int i, int j, int k) {
r = (i * N + j) * N + k; //行号
//四个列号
c1 = i * N + j + 1; //表示位于第i行j列的格子的列
c2 = N * N + i * N + k; //表示在第i行填k这个数字的列
c3 = 2 * N * N + j * N + k; //表示在第j列填k这个数字的列
c4 = 3 * N * N + ((i / 3) * 3 + j / 3) * N + k; //表示3*3格子中填k这个数字的列
}
void link(int r, int c) {
size++; //r行c列的值编号为size
C[size] = c;
S[c]++;
Row[size] = r;
D[size] = D[c];
U[D[c]] = size;
U[size] = c;
D[c] = size;
if (H[r] < 0) {
H[r] = size;
L[size] = size;
R[size] = size;
} else {
R[size] = R[H[r]];
L[R[H[r]]] = size;
L[size] = H[r];
R[H[r]] = size;
}
}
void remove(const int &cur) {
L[R[cur]] = L[cur];
R[L[cur]] = R[cur];
for (int i = D[cur]; i != cur; i = D[i]) {
for (int j = R[i]; j != i; j = R[j]) {
U[D[j]] = U[j];
D[U[j]] = D[j];
--S[C[j]];
}
}
}
void resume(const int &cur) {
for (int i = U[cur]; i != cur; i = U[i]) {
for (int j = L[i]; j != i; j = L[j]) {
++S[C[j]];
U[D[j]] = j;
D[U[j]] = j;
}
}
L[R[cur]] = cur;
R[L[cur]] = cur;
}
bool dance(int cur) {
int i, j, c, temp;
if (R[head] == head) {
for (i = 0; i < cur; i++) {
int x = (Row[Q[i]] - 1) / N / N;
int y = (Row[Q[i]] - 1) / N % N;
ans[x][y] = (Row[Q[i]] - 1) % N + 1;
}
return true;
}
temp = INF;
for (i = R[0]; i != 0; i = R[i])
if (S[i] < temp) {
temp = S[i];
c = i;
}
remove(c);
for (i = D[c]; i != c; i = D[i]) {
Q[cur] = i;
for (j = R[i]; j != i; j = R[j])
remove(C[j]);
if (dance(cur + 1))
return true;
for (j = L[i]; j != i; j = L[j])
resume(C[j]);
}
resume(c);
return false;
}
int init() {
int i, j, k, r, c1, c2, c3, c4;
char temp[5];
//Input begin
if (scanf("%s", temp) != 1)
return 0;
a[0][0] = (temp[0] == '?' ? 0 : temp[0] - '0');
for (i = 0; i < N; i++)
for (j = 0; j < N; j++) {
if (!i && !j)
continue;
scanf("%s", temp);
a[i][j] = (temp[0] == '?' ? 0 : temp[0] - '0');
}
//Input end
prepare(N * N * N, N * N * 4);
memset(vis, 0, sizeof (vis));
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
if (a[i][j]) {
place(r, c1, c2, c3, c4, i, j, a[i][j]);
link(r, c1), link(r, c2), link(r, c3), link(r, c4);
vis[c2] = vis[c3] = vis[c4] = 1; //记录下该列是否已经有了
}
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
if (!a[i][j]) {//对于没有填的进行建图
for (k = 1; k <= N; k++) {
place(r, c1, c2, c3, c4, i, j, k);
if (vis[c2] || vis[c3] || vis[c4])
continue;
link(r, c1), link(r, c2), link(r, c3), link(r, c4);
}
}
return 1;
}
void printresult() {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
if (j) {
printf(" ");
}
printf("%d", ans[i][j]);
}
printf("\n");
}
}
int main() {
int t = 0;
while (init()) {
dance(head);
if (t++)
printf("\n");
printresult();
}
return 0;
}
</code>