zoukankan      html  css  js  c++  java
  • POJ3076 Sudoku 舞蹈链 DLX

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

    去博客园看该题解

    题目(传送门)

    题意概括

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

    题解

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

    学完这个之后,再思考这一题。同样,每个位置每种取值4个信息。

    数独共256个格子,每个格子都得填一个数,那么,我们要精确覆盖每一个格子,所以我们首先建立1~256列。

    然后还有16行,每行1~16,每行都得精确覆盖,16行,又得建立16*16=256列;

    然后还有16列,每列1~16,同理。

    然后还有16个4*4的小格子,每个里面1~16,也同理。

    那么总共要建立4*256=1024列。

    代码

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    const int N=4100,M=1050,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 a[20][20],x[N],y[N],z[N];
    char s[20];
    int hash(int a,int b,int c){
        return a*256+b*16+c+1;
    }
    int main(){
        while (~scanf("%s",s+1)){
            for (int i=1;i<=16;i++){
                for (int j=1;j<=16;j++)
                    if (s[j]=='-')
                        a[i][j]=0;
                    else
                        a[i][j]=s[j]-'A'+1;
                if (i<16)
                    scanf("%s",s+1);
            }
            dlx.init(1024);
            int Row=0;
            for (int i=1;i<=16;i++)
                for (int j=1;j<=16;j++){
                    int st,en;
                    if (a[i][j]==0)
                        st=1,en=16;
                    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)/4)*4+(j-1)/4,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<=16;puts(""),i++)
                for (int j=1;j<=16;j++)
                    printf("%c",a[i][j]+'A'-1);
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    小米、华为与联想,背后隐含的三种模式(转)
    怎样使用jstack诊断Java应用程序故障(转)
    多线程中的死锁举例与分析(转)
    log4j的性能瓶颈定位与性能优化(org.apache.log4j.spi.RootLogger) (转)
    一个与Log4j相关的死锁(转)
    怎样取消shutdown关机命令?-shutdown命令的使用解析
    对软件体系结构的认识
    39个让你受益的HTML5教程
    5大AR应用窥探移动未来~你见过吗?
    Response.AddHeader使用实例
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/POJ3076.html
Copyright © 2011-2022 走看看