POJ2676 Sudoku 舞蹈链 DLX

欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解

题目(传送门)

题意概括

给出一个残缺的数独,求解。SPJ

 

题解

DLX  +  矩阵构建  (两个传送门)

 

代码

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=800,M=400,S=N*4+M;
struct DLX{
    int n,m,cnt;
    int x[S],y[S],L[S],R[S],U[S],D[S];
    int C[M],anscnt,ans[N];
    void init(int c){
        memset(x,0,sizeof x);
        memset(y,0,sizeof y);
        memset(L,0,sizeof L);
        memset(R,0,sizeof R);
        memset(U,0,sizeof U);
        memset(D,0,sizeof D);
        memset(C,0,sizeof C);
        memset(ans,0,sizeof ans);
        anscnt=0;
        m=c;
        for (int i=0;i<=m;i++)
            L[i]=i-1,R[i]=i+1,U[i]=D[i]=i;
        L[0]=m,R[m]=0,cnt=m;
    }
    void link(int i,int j){
        cnt++;
        x[cnt]=i;
        y[cnt]=j;
        L[cnt]=cnt-1;
        R[cnt]=cnt+1;
        D[cnt]=j;
        D[U[j]]=cnt;
        U[cnt]=U[j];
        U[j]=cnt;
        C[j]++;
    }
    void Delete(int k){
        L[R[k]]=L[k];
        R[L[k]]=R[k];
        for (int i=D[k];i!=k;i=D[i])
            for (int j=R[i];j!=i;j=R[j]){
                U[D[j]]=U[j];
                D[U[j]]=D[j];
                C[y[j]]--;
            }
    }
    void Reset(int k){
        L[R[k]]=k;
        R[L[k]]=k;
        for (int i=U[k];i!=k;i=U[i])
            for (int j=L[i];j!=i;j=L[j]){
                U[D[j]]=j;
                D[U[j]]=j;
                C[y[j]]++;
            }
    }
    bool solve(){
        if (R[0]==0)
            return true;
        anscnt++;
        int k=R[0];
        for (int i=R[k];i!=0;i=R[i])
            if (C[i]<C[k])
                k=i;
        Delete(k);
        for (int i=D[k];i!=k;i=D[i]){
            ans[anscnt]=x[i];
            for (int j=R[i];j!=i;j=R[j])
                Delete(y[j]);
            if (solve())
                return true;
            for (int j=L[i];j!=i;j=L[j])
                Reset(y[j]);
        }
        Reset(k);
        anscnt--;
        return false;
    }
}dlx;
int T,a[15][15],x[800],y[800],z[800];
char s[15];
int hash(int a,int b,int c){
    return a*81+b*9+c+1;
}
int main(){
    scanf("%d",&T);
    while (T--){
        for (int i=1;i<=9;i++){
            scanf("%s",s+1);
            for (int j=1;j<=9;j++)
                a[i][j]=s[j]-48;
        }
        dlx.init(9*9*4);
        int Row=0;
        for (int i=1;i<=9;i++)
            for (int j=1;j<=9;j++){
                int st,en;
                if (a[i][j]==0)
                    st=1,en=9;
                else
                    st=en=a[i][j];
                for (int k=st;k<=en;k++){
                    Row++;
                    x[Row]=i,y[Row]=j,z[Row]=k;
                    int first=dlx.cnt+1;
                    dlx.link(Row,hash(0,i-1,j-1));
                    dlx.link(Row,hash(1,i-1,k-1));
                    dlx.link(Row,hash(2,j-1,k-1));
                    dlx.link(Row,hash(3,((i-1)/3)*3+(j-1)/3,k-1));
                    dlx.L[first]=dlx.cnt;
                    dlx.R[dlx.cnt]=first;
                }
            }
        bool found=dlx.solve();
        for (int i=1;i<=dlx.anscnt;i++)
            a[x[dlx.ans[i]]][y[dlx.ans[i]]]=z[dlx.ans[i]];
        for (int i=1;i<=9;puts(""),i++)
            for (int j=1;j<=9;j++)
                printf("%d",a[i][j]);
    }
    return 0;
}

 

posted @ 2017-08-07 21:57  zzd233  阅读(319)  评论(0编辑  收藏  举报