POJ 3074 Sudoku (Dancing Links)

传送门:http://poj.org/problem?id=3074


DLX 数独的9*9的模板题。

具体建模详见下面这篇论文。其中9*9的数独怎么转化到精确覆盖问题,以及相关矩阵行列的定义都在下文中,描述的十分清晰

http://wenku.baidu.com/view/4ab7bd00a6c30c2259019eae.html

有关Dancing Links的英文论文详见下面链接

http://wenku.baidu.com/view/60eb28ded15abe23482f4d77.html

中文的:

http://wenku.baidu.com/view/d8f13dc45fbfc77da269b126.html



AC代码:

 

#include<iostream>

#include<cstring>

#include<string>

#include<cstdio>

#include<algorithm>

#include<vector>

#include<algorithm>



using namespace std;

//   列:(行+列+块)*9种可能+9*9个格子

//   行: 9*9*9  表示第i行第j列填k

const int MAXN=(9+9+9)*9+9*9+9*9*9*9*9*4+10;

#define INF 0xFFFFFF

int size;

int head,sz;

int U[MAXN],D[MAXN],L[MAXN],R[MAXN];

int H[MAXN],ROW[MAXN],C[MAXN],S[MAXN],O[MAXN];



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[C[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[C[j]];

            U[D[j]]=j;

            D[U[j]]=j;

          }

     }

     L[R[c]]=c;

     R[L[c]]=c;

}



bool dfs(int k)

{

    if(R[head]==head)

    {

        sort(O,O+9*9);

        int p=0;

        for(int i=0;i<9;i++)

        {

            for(int j=0;j<9;j++)

            {

                int num=O[p++];

                //cout<<num<<endl;

                num=num-(i*9+j)*9;

                printf("%d",num);

            }

        }

        printf("\n");

        return  true;

    }

    int s=INF,c;

    for (int t=R[head];t!=head;t=R[t])

    {

        if (S[t]<s)

        {

            s=S[t];

            c=t;

        }

     }

     remove(c);

     for(int i=D[c];i!=c;i=D[i])

     {

          O[k]=ROW[i];

          for(int j=R[i];j!=i;j=R[j])

              remove(C[j]);

          if(dfs(k+1))

               return  true;

          for(int j=L[i];j!=i;j=L[j])

               resume(C[j]);

     }

     resume(c);

     return  false;

}



void initDL(int n)

{

    head=0;

    for(int i=0;i<=n;i++)

    {

        U[i]=i;D[i]=i;

        L[i]=i-1;R[i]=i+1;

        S[i]=0;

    }

    R[n]=0;L[0]=n;S[0]=INF+1;

    sz=n+1;

    memset(H,0,sizeof(H));

}



void insert(int i, int j)

{

    if(H[i])

    {

        L[sz]=L[H[i]];

        R[sz]=H[i];

        L[R[sz]]=sz;

        R[L[sz]]=sz;

    }

    else

    {

        L[sz]=sz;

        R[sz]=sz;

        H[i]=sz;

    }

    U[sz]=U[j];

    D[sz]=j;

    U[D[sz]]=sz;

    D[U[sz]]=sz;

    C[sz]=j;

    ROW[sz]=i;

    ++S[j];

    ++sz;

}



char str[200];



void build()

{

    int p=0;

    initDL(9*9*4);

    for(int i=0;i<9;i++)

        for(int j=1;j<=9;j++,p++)

        {

            int base=(i*9+j-1)*9;

            if(str[p]=='.')

            {

                for(int k=1;k<=9;k++)

                {

                    int r;

                    r=base+k;

                    //第i行有数字k

                    insert(r,i*9+k);

                    //第j列有数字k

                    insert(r,9*9+(j-1)*9+k);

                    //第k块有数字k

                    int block=(j-1)/3*3+i/3;

                    insert(r,9*9*2+block*9+k);

                    //第i行j列有一个数字(限制一个格子只填一个数)

                    insert(r,9*9*3+i*9+j);

                }

            }

            else

            {

                int k=str[p]-'0';

                int r=base+k;

                //第i行有数字k

                insert(r,i*9+k);

                //第j列有数字k

                insert(r,9*9+(j-1)*9+k);

                //第k块有数字k

                int block=(j-1)/3*3+i/3;

                insert(r,9*9*2+block*9+k);

                //第i行j列有一个数字(限制一个格子只填一个数)

                insert(r,9*9*3+i*9+j);

            }

        }

}



int main()

{

    size=9; //9*9数独

    while(~scanf("%s",str))

    {

        if(strcmp(str,"end")==0)

            break;

        build();

        dfs(0);

    }

    return 0;

}


 

 

你可能感兴趣的:(sudo)