舞蹈鏈 - Sudoku

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 0x3f3f3f3f
using 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 0x3f3f3f3f
using 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章