(简单) POJ 3076 Sudoku , DLX+精确覆盖。

  Description

  A Sudoku grid is a 16x16 grid of cells grouped in sixteen 4x4 squares, where some cells are filled with letters from A to P (the first 16 capital letters of the English alphabet), as shown in figure 1a. The game is to fill all the empty grid cells with letters from A to P such that each letter from the grid occurs once only in the line, the column, and the 4x4 square it occupies. The initial content of the grid satisfies the constraints mentioned above and guarantees a unique solution. 
 
  Write a Sudoku playing program that reads data sets from a text file.

  这个题和POJ 3076没有什么区别,不过就是要注意一个问题,就是MaxNode不要太大,不然的话会MLE,对于数组不用开到MaxN*MaxM这么大,因为数独的很多方格都已经填上了,根本用不了那么大。。。。。。

  然后还要注意格式的问题,答案是要空行的。。。。。。

代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;

const int MaxN=16*16*16+10;
const int MaxM=4*16*16+10;
const int MaxNode=MaxN*MaxM/16;

int cas=1;

struct DLX
{
    int U[MaxNode],D[MaxNode],L[MaxNode],R[MaxNode],col[MaxNode],row[MaxNode];
    int size,n,m;
    int H[MaxN],S[MaxM];
    int ans[16*16+10],ans1[16*16+10];

    void init(int _n,int _m)
    {
        n=_n;
        m=_m;

        for(int i=0;i<=m;++i)
        {
            U[i]=D[i]=i;
            L[i]=i-1;
            R[i]=i+1;
            row[i]=0;

            S[i]=0;
        }
        L[0]=m;
        R[m]=0;

        size=m;

        for(int i=1;i<=n;++i)
            H[i]=-1;
    }

    void Link(int r,int c)
    {
        col[++size]=c;
        row[size]=r;
        ++S[c];

        U[size]=U[c];
        D[size]=c;
        D[U[c]]=size;
        U[c]=size;

        if(H[r]==-1)
            H[r]=L[size]=R[size]=size;
        else
        {
            L[size]=L[H[r]];
            R[size]=H[r];
            R[L[H[r]]]=size;
            L[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])
            {
                U[D[j]]=j;
                D[U[j]]=j;
                ++S[col[j]];
            }

        L[R[c]]=R[L[c]]=c;
    }

    void showans(int d)
    {
        if(cas!=1)
            cout<<endl;

        for(int i=0;i<d;++i)
            ans1[(ans[i]-1)/16+1]=(ans[i]-1)%16+1;

        for(int i=1;i<=256;++i)
        {
            cout<<char(ans1[i]-1+‘A‘);

            if(i%16==0)
                cout<<endl;
        }

        ++cas;
    }

    bool Dance(int d)
    {
        if(R[0]==0)
        {
            showans(d);
            return 1;
        }

        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 1;

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

        resume(c);

        return 0;
    }

    void display()
    {
        for(int i=R[0];i!=0;i=R[i])
        {
            cout<<i<<‘ ‘;
            for(int j=D[i];j!=i;j=D[j])
                cout<<‘(‘<<j<<‘,‘<<(row[j]-1)%16+1<<‘)‘<<‘ ‘;

            cout<<endl;
        }
    }
};

DLX dlx;
char s[300];

void getchange(int &r,int &c1,int &c2,int &c3,int &c4,int i,int j,int k)
{
    r=(i*16+j)*16+k;
    c1=i*16+j+1;
    c2=256+i*16+k;
    c3=512+j*16+k;
    c4=768+((i/4)*4+(j/4))*16+k;
}

void slove()
{
    int r,c1,c2,c3,c4;

    dlx.init(16*16*16,4*16*16);

    for(int i=0;i<16;++i)
        for(int j=0;j<16;++j)
            for(int k=1;k<=16;++k)
                if(s[i*16+j]==‘-‘ || s[i*16+j]-‘A‘+1==k)
                {
                    getchange(r,c1,c2,c3,c4,i,j,k);

                    dlx.Link(r,c1);
                    dlx.Link(r,c2);
                    dlx.Link(r,c3);
                    dlx.Link(r,c4);
                }

/*    for(int i=1;i<=256;++i)
        for(int j=1;j<=16;++j)
            if(s[i-1]==‘-‘ || (j+(i-1)*16-1)%16+1==s[i-1]-‘A‘+1)
                dlx.Link(j+(i-1)*16,i);

    for(int i=1;i<=256;++i)
        for(int j=1;j<=16;++j)
            if(s[i-1]==‘-‘ || (16*(j-1)+(i-1)%16+1+256*((i-1)/16)-1)%16+1==s[i-1]-‘A‘+1)
                dlx.Link(16*(j-1)+(i-1)%16+1+256*((i-1)/16),i+256);

    for(int i=1;i<=256;++i)
        for(int j=1;j<=16;++j)
            if(s[i-1]==‘-‘ || ((j-1)*256+i-1)%16+1==s[i-1]-‘A‘+1)
                dlx.Link((j-1)*256+i,i+512);

    for(int i=1;i<=4;++i)
        for(int j=1;j<=4;++j)
            for(int k=1;k<=16;++k)
                for(int l=1;l<=4;++l)
                    for(int m=1;m<=4;++m)
                        if(s[(i-1)*64+(j-1)*16+k-1]==‘-‘ || ((i-1)*1024+(j-1)*64+k+(l-1)*256+(m-1)*16-1)%16+1==s[(i-1)*64+(j-1)*16+k-1]-‘A‘+1)
                            dlx.Link((i-1)*1024+(j-1)*64+k+(l-1)*256+(m-1)*16,(i-1)*64+(j-1)*16+k+768);

    for(int i=0;i<256;++i)
        if(s[i]!=‘-‘)
        {
            dlx.ans1[i+1]=s[i]-‘A‘+1;

            dlx.remove(i+1);

            for(int j=dlx.D[i+1];j!=i+1;j=dlx.D[j])
            {
                if((dlx.row[j]-1)%16+1==s[i]-‘A‘+1)
                {
                    for(int k=dlx.R[j];k!=j;k=dlx.R[k])
                        dlx.remove(dlx.col[k]);

                    break;
                }
            }
        }
*/
    dlx.Dance(0);
}

int main()
{
    ios::sync_with_stdio(false);

    char st[100];

    while(cin>>s)
    {
        for(int i=0;i<15;++i)
        {
            cin>>st;
            strcat(s,st);
        }

        slove();
    }

    return 0;
}

时间: 2024-10-07 21:22:41

(简单) POJ 3076 Sudoku , DLX+精确覆盖。的相关文章

POJ 3076 Sudoku DLX精确覆盖

DLX精确覆盖模版题..... Sudoku Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 4416   Accepted: 2143 Description A Sudoku grid is a 16x16 grid of cells grouped in sixteen 4x4 squares, where some cells are filled with letters from A to P (the fi

(简单) POJ 3074 Sudoku, DLX+精确覆盖。

Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example, . 2 7 3 8 . . 1 . . 1 . . . 6 7 3 5 . . . . . . . 2 9 3 . 5 6 9 2 . 8 . . . . . . . . . . . 6 . 1 7 4 5 . 3 6 4 . . . . . . . 9 5 1

POJ 3047 Sudoku DLX精确覆盖

DLX精确覆盖.....模版题 Sudoku Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8336   Accepted: 2945 Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example, . 2 7 3 8 . . 1 . . 1 . .

POJ 3074 Sudoku DLX精确覆盖

DLX精确覆盖.....模版题 Sudoku Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8336   Accepted: 2945 Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example, . 2 7 3 8 . . 1 . . 1 . .

poj 3076 Sudoku dlx解数独

16*16的数独,类似poj 3074. //poj 3076 //sep9 #include <cstdio> #include <cstdlib> #define INT_MAX 2147483647 using namespace std; const int col_num=16*16*4; const int row_num=16*16*16+10; const int head=0; const int MAX=row_num*4+col_num+10; const i

(中等) HDU 4069 Squiggly Sudoku , DLX+精确覆盖。

Description Today we play a squiggly sudoku, The objective is to fill a 9*9 grid with digits so that each column, each row, and each of the nine Connecting-sub-grids that compose the grid contains all of the digits from 1 to 9. Left figure is the puz

(简单) HUST 1017 Exact cover , DLX+精确覆盖。

Description There is an N*M matrix with only 0s and 1s, (1 <= N,M <= 1000). An exact cover is a selection of rows such that every column has a 1 in exactly one of the selected rows. Try to find out the selected rows. DLX精确覆盖的模板题...... 代码如下: //HUST 1

POJ 3076 数独DLX

Sudoku Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 4203   Accepted: 2051 Description A Sudoku grid is a 16x16 grid of cells grouped in sixteen 4x4 squares, where some cells are filled with letters from A to P (the first 16 capital l

POJ 3076 Sudoku (dancing links)

题目大意: 16*16的数独. 思路分析: 多说无益. 想说的就是dancing links 的行是按照 第一行第一列填 1 第一行第二列填 2 -- 第一行第十五列填15 第一行第二列填 1 -- 第二行.... 列的纺织则是 第一行放1,第一行放2,..第十六行放16...第一列放1..第一列放2...第十六列放16..第一块区域放1 ....然后在最后81位就是放自己的位置,准确的说就是 r*m+c. #include <cstdio> #include <iostream>