AcWing - 169 - 数独2 - 舞蹈链

Posted inko

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AcWing - 169 - 数独2 - 舞蹈链相关的知识,希望对你有一定的参考价值。

https://www.acwing.com/problem/content/description/171/

舞蹈链还是比较好,抄了一个看起来可以改的模板?

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int inf  = (-1u>>1); 
#define m 4
#define n 16
#define N n*n*n
#define M 4*n*n
char s[20][20];
struct node{
    int r,c;
    node *L,*R,*U,*D;
};
node DD[N*4+5], row[N+5], col[M+5], head;
int cnt, size[M+5], ans[n+5][n+5];
inline void init(int r, int c){
      cnt = 0;
      head.L = head.R = head.U = head.D = &head;
      for (int i = 0; i < c; i++){
            col[i].c = i;
            col[i].r = r;
            col[i].L = &head;
            col[i].R = head.R;
            col[i].L->R = col[i].R->L = &col[i];
            col[i].U = col[i].D = &col[i];
            size[i] = 0; 
      } 
      for (int i = r - 1; i >= 0; i--){
            row[i].r = i;
            row[i].c = c;
            row[i].D = &head;
            row[i].U = head.U;
            row[i].U->D = row[i].D->U = &row[i];
            row[i].L = row[i].R = &row[i]; 
      }
}

inline void delLR(node *p){
      p->L->R = p->R;
      p->R->L = p->L;
}
inline void delUD(node *p){
      p->U->D = p->D;
      p->D->U = p->U;
} 
inline void recLR(node *p){
      p->L->R = p->R->L = p;
}
inline void recUD(node *p){
      p->U->D = p->D->U = p;
} 
inline void add(int r, int c){
      node *p = &DD[cnt++];
      p->c = c;
      p->r = r;
      p->U = &col[c];
      p->D = col[c].D;
      p->U->D = p->D->U = p;
      p->R = &row[r];
      p->L = row[r].L;
      p->L->R = p->R->L = p;
      size[c]++;
} 


void cover(int c){
      if (c == M)
           return;
      delLR(&col[c]);
      node *p, *q;
      for (p = col[c].D; p != (&col[c]); p = p->D){
             for (q = p->L ; q != p; q = q->L){
                     if (q->c == M)
                          continue;
                     delUD(q);
                     size[q->c]--;
             }
      }
} 

void resume(int c){
      if (c == M)
           return ;
      node *p, *q;
      for (p = col[c].U; p != (&col[c]); p = p->U){
           for (q = p->R; q != p; q = q->R){
                 if (q->c == M)
                      continue;
                 recUD(q);
                 size[q->c]++;
           }
      }
      recLR(&col[c]);
}

bool DLX(int k){
     node *p;
     if (head.L == (&head)){
             for (int i = 0; i < n; i++){
                  for (int j = 0; j < n; j++)
                      printf("%c", ans[i][j] + 'A');
                  puts("");
             }
             puts(""); 
             return true;
     }
     int MIN = inf, c = 1;
     for (p = head.R; p != (&head); p = p->R){
            if (size[p->c] < MIN){
                    MIN = size[p->c];
                    c = p->c;
            }
     }
     cover(c);
     for (p = col[c].D; p != (&col[c]); p = p->D){
            node *q;
            for (q = p->L; q != p; q = q->L){
                cover(q->c);
            }
            int rr = p->r;
            ans[rr / (n*n)][(rr/n) % n] = rr % n;
            if (DLX(k + 1))
                return true;
            for (q = p->R; q != p; q = q->R)
                resume(q->c);
     }
     resume(c);
     return false;
} 


void insert(int i, int j, int k){
     int r = (i * n + j) * n + k - 1;
     add(r, i * n + k - 1);
     add(r, n * n + j * n + k - 1);
     add(r, 2 * n * n + (i / m * m + j / m ) * n + k - 1);
     add(r, 3 * n * n + i * n + j);
} 

void Sudoku(){
      int k; 
      for (int i = 0; i < n; i++){
           for (int j = 0; j < n; j++){
                if (s[i][j] != '-')
                      insert(i, j, s[i][j] - 'A' + 1);
                else {
                      for (int k = 1; k <= n; k++)
                            insert(i, j, k);
                }
           }
      }
      if (!DLX(0))
             puts("NO Solution!");
} 

int main(){
      //freopen("in.txt", "r", stdin);
      //freopen("out.txt", "w", stdout); 
      while (scanf("%s", s[0]) != EOF){
             for (int i = 1; i < n; i++)scanf("%s", s[i]); 
             init(N, M);
             Sudoku();
      }
     // getchar();
      return 0;
} 

作者:zhagoodwell
链接:https://www.acwing.com/solution/acwing/content/4110/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

以上是关于AcWing - 169 - 数独2 - 舞蹈链的主要内容,如果未能解决你的问题,请参考以下文章

P1074靶形数独

dancing links

DFS剪枝数独(简单版)

DFS剪枝数独(简单版)

AcWing 1762. 牛的洗牌

软件工程数独——需求分析2