POJ3074(Dance Links X算法)

图文并茂的dance link X 算法讲解(点击我啊)

dance link X算法是用来解决精确覆盖问题,例如在一个01矩阵中,找n行,能使得每一列都只有一个1,其余全是0. 而怎么将求解数独转化为DLX能解决的问题呢? 假设是一个9*9的数独,每一行,每一列,每个宫都要有1~9这9个数,每一个格子都有9个状态,所以一共有9*9*9的状态,所以DLX要建729行,然后用9*9来表示每个格子都有数字了,每行每列每宫都要9*9来表示当前行/列/宫有数字k了.一共4*9*9列.

直接上题目吧POJ3074

sourse code:cpp

  1 #include <cstdio>
  2 #include <cstring>
  3 using namespace std;
  4 const int N = 9; //3*3 数独
  5 const int MaxN = N * N * N + 10;
  6 const int MaxM = N * N * 4 + 10;
  7 const int maxnode = MaxN * 4 + MaxM + 10;
  8 char g[MaxN];
  9 struct DLX {
 10     int n, m, size;
 11     int U[maxnode], D[maxnode], R[maxnode], L[maxnode], Row[maxnode], Col[maxnode];
 12     int H[MaxN], S[MaxM];//S维护每一列有多少个点,H维护每一行的头
 13     int ansd, ans[MaxN];
 14     void init(int _n, int _m) {//m维护每一列,n维护每一行
 15         n = _n;
 16         m = _m;
 17         for (int i = 0; i <= m; i++) {
 18             S[i] = 0;
 19             U[i] = D[i] = i;
 20             L[i] = i - 1;
 21             R[i] = i + 1;
 22         }
 23         R[m] = 0; L[0] = m;
 24         size = m;
 25         for (int i = 1; i <= n; i++)H[i] = - 1;
 26     }
 27     void Link(int r, int c) {
 28         ++S[Col[++size] = c];//size像是每个点的编号
 29         Row[size] = r;
 30         D[size] = D[c];
 31         U[D[c]] = size;
 32         U[size] = c;
 33         D[c] = size;
 34         if (H[r] < 0)H[r] = L[size] = R[size] = size;
 35         else {
 36             R[size] = R[H[r]];
 37             L[R[H[r]]] = size;
 38             L[size] = H[r];
 39             R[H[r]] = size;
 40         }
 41     }
 42     void remove(int c) {
 43         L[R[c]] = L[c]; R[L[c]] = R[c];
 44         for (int i = D[c]; i != c; i = D[i])
 45             for (int j = R[i]; j != i; j = R[j]) {
 46                 U[D[j]] = U[j];//断开j
 47                 D[U[j]] = D[j];
 48                 -- S[Col[j]];
 49             }
 50     }
 51     void resume(int c) {
 52         for (int i = U[c]; i != c; i = U[i])
 53             for (int j = L[i]; j != i; j = L[j])
 54                 ++S[Col[U[D[j]] = D[U[j]] = j]];
 55         L[R[c]] = R[L[c]] = c;
 56     }
 57     bool Dance(int d) {
 58         if (R[0] == 0) {
 59             for (int i = 0; i < d; i++)g[(ans[i] - 1) / 9] = (ans[i] - 1) % 9 + '1';
 60             for (int i = 0; i < N * N; i++)printf("%c", g[i]);
 61             printf("\n");
 62             return true;
 63         }
 64         int c = R[0];
 65         for (int i = R[0]; i != 0; i = R[i])
 66             if (S[i] < S[c])
 67                 c = i;
 68         remove(c);
 69         for (int i = D[c]; i != c; i = D[i]) {
 70             ans[d] = Row[i];
 71             for (int j = R[i]; j != i; j = R[j])remove(Col[j]);
 72             if (Dance(d + 1))return true;
 73             for (int j = L[i]; j != i; j = L[j])resume(Col[j]);
 74         }
 75         resume(c);
 76         return false;
 77     }
 78 };
 79 void place(int &r, int &c1, int &c2, int &c3, int &c4, int i, int j, int k) {
 80     r = (i * N + j) * N + k;
 81     c1 = i * N + j + 1;
 82     c2 = N * N + i * N + k;
 83     c3 = N * N * 2 + j * N + k;
 84     c4 = N * N * 3 + ((i / 3) * 3 + (j / 3)) * N + k;
 85 }
 86 DLX dlx;
 87 int main() {
 88     while (scanf("%s", g) == 1) {
 89         if (strcmp(g, "end") == 0)break;
 90         dlx.init(N * N * N, N * N * 4);
 91         int r, c1, c2, c3, c4;
 92         for (int i = 0; i < N; i++)
 93             for (int j = 0; j < N; j++)
 94                 for (int k = 1; k <= N; k++)
 95                     if (g[i * N + j] == '.' || g[i * N + j] == '0' + k) {
 96                         place(r, c1, c2, c3, c4, i, j, k);
 97                         dlx.Link(r, c1);
 98                         dlx.Link(r, c2);
 99                         dlx.Link(r, c3);
100                         dlx.Link(r, c4);
101                     }
102         dlx.Dance(0);
103     }
104     return 0;
105 }

猜你喜欢

转载自www.cnblogs.com/wafirst/p/9559260.html
今日推荐