舞蹈链 - Sudoku

来源:互联网 发布:手机wifi服务器端口 编辑:程序博客网 时间:2024/06/10 09:04

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=65998#problem/F

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=65998#problem/G

bin神专题里的两个数独问题, 后面还有一个变形的数独(不是普通的九宫格 十六宫格)

这里一个是九宫格, 一个是十六宫格的数独…

具体的构图在前一篇的那里有说到一位菊苣的blog, 他的介绍写的非常好, 可以去看一下..

主要是4个约束条件:

  1. 每一个格子都要放一个数
  2. 每一行要有9种数字,不许重复
  3. 每一列要有9种数字,不许重复
  4. 每一个宫要有9种数字,不许重复

如果是16的就直接把上面改成16..

转化的和构图的话, 还是看菊苣的介绍吧..我就重复发明轮子了..

九宫格的: POJ3074

#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<string>#include<stack>#include<queue>#include<vector>#include<map>#include<set>#include<iostream>#define pb push_back#define INF 0x3f3f3f3fusing namespace std;typedef unsigned long long ULL;typedef long long LL;const int mod = 1000000007;const int N = 9; //3*3数独const int MaxN = N*N*N + 10;const int MaxM = N*N*4 + 10;const int maxnode = MaxN*4 + MaxM + 10;char g[MaxN];struct DLX {    int n,m,size;    int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode];    int H[MaxN],S[MaxM];    int ansd,ans[MaxN];    void init(int _n,int _m) {        n = _n;        m = _m;        for(int i = 0;i <= m;i++) {            S[i] = 0;            U[i] = D[i] = i;            L[i] = i-1;            R[i] = i+1;        }        R[m] = 0; L[0] = m;        size = m;        for(int i = 1;i <= n;i++)H[i] = -1;    }    void Link(int r,int c) {        ++S[Col[++size]=c];        Row[size] = r;        D[size] = D[c];        U[D[c]] = size;        U[size] = c;        D[c] = size;        if(H[r] < 0)H[r] = L[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(int c) {        L[R[c]] = L[c]; R[L[c]] = R[c];        for(int i = D[c];i != c;i = D[i])            for(int j = R[i];j != i;j = R[j]){                U[D[j]] = U[j];                D[U[j]] = D[j];                --S[Col[j]];            }    }    void resume(int c) {        for(int i = U[c];i != c;i = U[i])            for(int j = L[i];j != i;j = L[j])                ++S[Col[U[D[j]]=D[U[j]]=j]];        L[R[c]] = R[L[c]] = c;    }    bool Dance(int d) {        if(R[0] == 0) {            for(int i = 0;i < d;i++)g[(ans[i]-1)/9] = (ans[i]-1)%9 + '1';            for(int i = 0;i < N*N;i++)printf("%c",g[i]);            printf("\n");            return true;        }        int c = R[0];        for(int i = R[0];i != 0;i = R[i])            if(S[i] < S[c])                c = i;        remove(c);        for(int i = D[c];i != c;i = D[i]) {            ans[d] = Row[i];            for(int j = R[i];j != i;j = R[j])remove(Col[j]);            if(Dance(d+1))return true;            for(int j = L[i];j != i;j = L[j])resume(Col[j]);        }        resume(c);        return false;    }};inline void get(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; c2 = N*N+i*N+k;    c3 = N*N*2+j*N+k; c4 = N*N*3+((i/3)*3+(j/3))*N+k;}DLX sol;char s[100];void solve() {    while(~scanf("%s", s)){        if(!strcmp(s, "end")) return ;        sol.init(N*N*N, N*N*4);        int r, c1, c2, c3, c4;        for(int i=0; i<N; i++)            for(int j=0; j<N; j++)                for(int k=1; k<=N; k++) if(s[i*N+j] == '.' || s[i*N+j] == '0' + k){                    get(r, c1, c2, c3, c4, i, j, k);                    sol.Link(r, c1); sol.Link(r, c2);                    sol.Link(r, c3); sol.Link(r, c4);                }        sol.Dance(0);    }}int main(void) {#ifdef DK    freopen("/home/dk/桌面/1.in","r",stdin);#endif // DK    solve();    return 0;}

十六宫格的: ZOJ 3122

#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<string>#include<stack>#include<queue>#include<vector>#include<map>#include<set>#include<iostream>#define pb push_back#define INF 0x3f3f3f3fusing namespace std;typedef unsigned long long ULL;typedef long long LL;const int mod = 1000000007;const int N = 16;const int MaxN = N*N*N + 10;const int MaxM = N*N*4 + 10;const int maxnode = MaxN*4 + MaxM + 10;char g[MaxN];struct DLX {    int n,m,size;    int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode];    int H[MaxN],S[MaxM];    int ansd,ans[MaxN];    void init(int _n,int _m) {        n = _n; m = _m;        for(int i = 0;i <= m;i++) {            S[i] = 0;            U[i] = D[i] = i;            L[i] = i-1;            R[i] = i+1;        }        R[m] = 0; L[0] = m;        size = m;        for(int i = 1;i <= n;i++)H[i] = -1;    }    void Link(int r,int c) {        ++S[Col[++size]=c];        Row[size] = r;        D[size] = D[c];        U[D[c]] = size;        U[size] = c;        D[c] = size;        if(H[r] < 0) H[r] = L[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(int c) {        L[R[c]] = L[c]; R[L[c]] = R[c];        for(int i = D[c];i != c;i = D[i])            for(int j = R[i];j != i;j = R[j]){                U[D[j]] = U[j];                D[U[j]] = D[j];                --S[Col[j]];            }    }    void resume(int c) {        for(int i = U[c];i != c;i = U[i])            for(int j = L[i];j != i;j = L[j])                ++S[Col[U[D[j]]=D[U[j]]=j]];        L[R[c]] = R[L[c]] = c;    }    bool Dance(int d) {        //printf("r->%d d : %d\n", R[0], d);        if(R[0] == 0) {            ansd = d;            for(int i = 0; i < d; i++) g[(ans[i]-1)/N] = (ans[i]-1)%N + 'A';            for(int i = 0; i < N; i++) {                for(int j=0; j<N; j++)                    printf("%c", g[i*N+j]);                puts("");            }            return true;        }        int c = R[0];        //printf("c : %d down : %d\n", c, D[c]);        for(int i = R[0];i != 0;i = R[i])            if(S[i] < S[c]){                c = i;                //printf("i : %d S[i] : %d\n", i, S[i]);            }        //printf("c : %d down : %d\n", c, D[c]);        remove(c);        for(int i = D[c];i != c;i = D[i]) {            ans[d] = Row[i];            for(int j = R[i];j != i;j = R[j])remove(Col[j]);            if(Dance(d+1)) return true;            for(int j = L[i];j != i;j = L[j])resume(Col[j]);        }        resume(c);        return false;    }};inline void get(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;    c2 = N*N+i*N+k;    c3 = N*N*2+j*N+k;    c4 = N*N*3+((i/4)*4+(j/4))*N+k;}DLX dlx;char s[20][100];inline int read() {    for(int i=0; i<N; i++) if(scanf("%s", s[i]) == EOF)        return false;    //for(int i=0; i<N; i++) printf("%s\n", s[i]);    return true;}void solve() {    int first = 1;    while(read()){        if(first) first = 0;        else puts("");        dlx.init(N*N*N, N*N*4);        int r, c1, c2, c3, c4;        for(int i=0; i<N; i++)            for(int j=0; j<N; j++)                for(int k=1; k<=N; k++) if(s[i][j] == '-' || s[i][j] == 'A' + k-1){                    get(r, c1, c2, c3, c4, i, j, k);                    dlx.Link(r, c1); dlx.Link(r, c2);                    dlx.Link(r, c3); dlx.Link(r, c4);                    //printf("r:%d c1:%d c2:%d c3:%d c4:%d\n", r, c1, c2, c3, c4);                }        dlx.Dance(0);    }}int main(void) {#ifdef DK    freopen("/home/dk/桌面/1.in","r",stdin);#endif // DK    solve();    return 0;}
0 0