POJ 3076 Sudoku (DLX)

来源:互联网 发布:知乎 高帮帆布鞋搭配 编辑:程序博客网 时间:2024/05/05 19:17

16*16 的数独,DLX的最爱。想了一会儿空着的列要不要删掉,突然发现其实随它搜就好了,只影响深度不影响宽度。或者手动删除一下也没有大碍。

/* Created Time: Thursday, November 21, 2013 PM08:36:56 CST */#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std;const int N = 20;const int MAXC = 4*256+7, MAXNODE = 4*256*16*16+7, MAXR = 16*16+7;struct DLX {        int S[MAXC];                                        // 列节点数    int n,sz;                                           // 列数,节点数    int L[MAXNODE],R[MAXNODE],U[MAXNODE],D[MAXNODE];    // 十字链表    int ans[MAXR],ansd;                                 // 解    int row[MAXNODE],col[MAXNODE];                      // 对应的行列号    void init(int num) {        n = num;        for (int i = 0; i <= n; i ++) {            U[i] = i; D[i] = i; L[i] = i-1; R[i] = i+1;        }        L[0] = n; R[n] = 0;        sz = n+1;        memset(S,0,sizeof(S));    }    void add_raw(int r,vector <int> line) {        int first = sz;        for (int i = 0; i < line.size(); i ++) {            int c = line[i];            L[sz] = sz-1; R[sz] = sz+1; U[sz] = U[c]; D[sz] = c;            D[U[c]] = sz; U[c] = sz;            row[sz] = r; col[sz] = c;            S[c] ++; sz ++;        }        R[sz-1] = first; L[first] = sz-1;    }#define FOR(i,A,s) for (int i = A[s]; i != s; i = A[i])    void remove(int c) {        L[R[c]] = L[c];        R[L[c]] = R[c];        FOR(i,D,c) FOR(j,R,i) {                U[D[j]] = U[j]; D[U[j]] = D[j]; S[col[j]] --;            }    }    void restore(int c) {        FOR(i,U,c) FOR(j,L,i) {            U[D[j]] = j; D[U[j]] = j; S[col[j]] ++;        }        L[R[c]] = c;        R[L[c]] = c;    }    bool dfs(int dep) {        if (R[0]==0) {            ansd = dep;            return true;        }        int c = R[0];        FOR(i,R,0)            if (S[i]<S[c]) c = i;        remove(c);        FOR(i,D,c) {            ans[dep] = row[i];            FOR(j,R,i) remove(col[j]);            if (dfs(dep+1)) return true;            FOR(j,L,i) restore(col[j]);        }        restore(c);        return false;    }    bool solve(vector <int> &v) {        v.clear();        if (!dfs(0)) return false;        for (int i = 0; i < ansd; i ++) v.push_back(ans[i]);        return true;    }};/*******************************************************************/DLX solver;char mat[N][N];int encode(int a,int b,int c) { return (a*16+b)*16+c+1; }void decode(int v,int &a,int &b,int &c) {    v --;    c = v%16; v /= 16;    b = v%16; v /= 16;    a = v;}int get_b(int x,int y) { return x/4*4+y/4; }const int POS = 0,ROW = 1,COL = 2,BLO = 3;void get(int x,int y) {    int b = get_b(x,y);    for (int i = 0; i < 16; i ++)    {        if (mat[x][y]!='-' && mat[x][y]!=i+'A') continue;        vector <int> v;        v.push_back(encode(POS,x,y));        v.push_back(encode(ROW,x,i));        v.push_back(encode(COL,y,i));        v.push_back(encode(BLO,b,i));        solver.add_raw(encode(x,y,i),v);    }}void work() {    solver.init(4*256);    for (int i = 0; i < 16; i ++) for (int j = 0; j < 16; j ++)        get(i,j);        vector <int> v;    solver.solve(v);    for (int i = 0; i < v.size(); i ++)    {        int a,b,c;        decode(v[i],a,b,c);        mat[a][b] = c+'A';    }    for (int i = 0; i < 16; i ++) puts(mat[i]);}int main() {    bool first = true;    while (~scanf("%s",mat[0])) {        for (int i = 1; i < 16; i ++) scanf("%s",mat[i]);        if (first) first = false; else puts("");        work();    }    return 0;}


原创粉丝点击