Sudoku HDU - 5547

舞蹈鏈解決數獨問題,也是很經典的一個數獨問題
直接套用的書上的模版

//leehaoze
#include <iostream>
#include <deque>
#include <string>
#include <vector>
#include <queue>
#include <cstdio>
#include <stack>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <cstdio>
#include <cmath>
#include <cstdlib>

using namespace std;
const int INF = 1<<29;
#define INC_SAT( val ) (val = ((val)+1 > (val)) ? (val)+1 : (val))
#define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )
#define ULL unsigned long long


const int maxn = 4 * 4 * 4 * 4 * 4 * 4;
const int maxnode = 4 * 4 * 4 * 4 * 4 * 4;
const int maxr = 4 * 4 * 4 * 4 * 4 * 4;

struct DLX{
    int n, sz;
    int S[maxn];

    int row[maxnode],col[maxnode];
    int L[maxnode],R[maxnode],U[maxnode],D[maxnode];

    int ansd,ans[maxr];

    void init(int n){
        this->n = n;
        for(int i = 0;i <= n;++i){
            U[i] = i;D[i] = i;L[i]=i-1;R[i] = i+1;
        }
        R[n] = 0;L[0] = n;
        sz =n + 1;
        memset(S,0,sizeof S);
    }

    void addRow(int r,vector<int> columns){
        int first =sz;
        for (int i = 0; i < columns.size(); ++i) {
            int c= columns[i];
            L[sz] = sz - 1;
            R[sz] = sz + 1;
            D[sz] = c;
            U[sz] = U[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){
            ++S[col[j]];
            U[D[j]] = j;
            D[U[j]] = j;
        }
    L[R[c]] = c;
    R[L[c]] = c;
}

    bool dfs(int d){
        if(R[0] == 0){
            ansd = d;
            return true;
        }
        int c = R[0];
        FOR(i,R,0)if(S[i] < S[c] ) c= i;

        remove(c);
        FOR(i,D,c){
            ans[d] = row[i];
            FOR(j,R,i)remove(col[j]);
            if(dfs(d+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;

const int SLOT = 0;
const int ROW = 1;
const int COL = 2;
const int SUB = 3;

int encode(int a,int b,int c){
    return a*16+b*4+c+1;
}

void decode(int code,int &a,int &b,int &c){
    code--;
    c = code%4; code /= 4;
    b = code%4; code /= 4;
    a = code;
}

char puzzle[5][5];

void read(){
    for (int i = 0; i < 4; ++i) {
        scanf("%s",puzzle[i]);
    }
}

int main() {
    int T,cases = 1;
    scanf("%d",&T);
    while(T--) {
        read();
        solver.init(64);
        for (int r = 0; r < 4; ++r)
            for (int c = 0; c < 4; ++c)
                for (int v = 0; v < 4; ++v)
                    if (puzzle[r][c] == '*' || puzzle[r][c] == '1' + v) {
                        vector<int> columns;
                        columns.push_back(encode(SLOT, r, c));
                        columns.push_back(encode(ROW, r, v));
                        columns.push_back(encode(COL, c, v));
                        columns.push_back(encode(SUB, r / 2 * 2 + c / 2, v));
                        solver.addRow(encode(r, c, v), columns);
                    }
        vector<int> ans;
        solver.solve(ans);
        for (int i = 0; i < ans.size(); ++i) {
            int r,c,v;
            decode(ans[i],r,c,v);
            puzzle[r][c] = '1' + v;
        }
        printf("Case #%d:\n",cases++);
        for (int i = 0; i < 4; ++i) {
            printf("%s\n",puzzle[i]);
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章