DLX(16*16Sudoku+poj3076,9*9Sudoku+poj3074

Language:
Sudoku
Time Limit: 10000MS Memory Limit: 65536K
Total Submissions: 4393 Accepted: 2133

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.

Input

Each data set encodes a grid and contains 16 strings on 16 consecutive lines as shown in figure 2. The i-th string stands for the i-th line of the grid, is 16 characters long, and starts from the first position of the line. String characters are from the set {A,B,…,P,-}, where – (minus) designates empty grid cells. The data sets are separated by single empty lines and terminate with an end of file.

Output

The program prints the solution of the input encoded grids in the same format and order as used for input.

Sample Input

--A----C-----O-I
-J--A-B-P-CGF-H-
--D--F-I-E----P-
-G-EL-H----M-J--
----E----C--G---
-I--K-GA-B---E-J
D-GP--J-F----A--
-E---C-B--DP--O-
E--F-M--D--L-K-A
-C--------O-I-L-
H-P-C--F-A--B---
---G-OD---J----H
K---J----H-A-P-L
--B--P--E--K--A-
-H--B--K--FI-C--
--F---C--D--H-N-

Sample Output

FPAHMJECNLBDKOGI
OJMIANBDPKCGFLHE
LNDKGFOIJEAHMBPC
BGCELKHPOFIMAJDN
MFHBELPOACKJGNID
CILNKDGAHBMOPEFJ
DOGPIHJMFNLECAKB
JEKAFCNBGIDPLHOM
EBOFPMIJDGHLNKCA
NCJDHBAEKMOFIGLP
HMPLCGKFIAENBDJO
AKIGNODLBPJCEFMH
KDEMJIFNCHGAOPBL
GLBCDPMHEONKJIAF
PHNOBALKMJFIDCEG
IAFJOECGLDPBHMNK


今天又看了一遍,想明白了

行表示r行c列要填的是v,列表示的是要满足的状态,slot表示a行b列要有字母,row表示a行要有字母b,col表示a列要有字母b。sub表示子矩阵a要有字母b,这样就把数独问题转化成了精确覆盖问题,共有16*16*16行,16*16*4列,前16*16列表示slot,以此类推。这样进行编码的时候,就相当于进行16进制转化

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=16*16*16+10;
const int maxm=16*16*4+10;
const int maxnode=maxn*maxm;
const int SIGMA_SIZE=16;
const int SLOT=0;
const int ROW=1;
const int COL=2;
const int SUB=3;
char s[20][20];

struct DLX
{
    int n,m,size;
    int U[maxnode],D[maxnode],L[maxnode],R[maxnode];
    int H[maxn],S[maxm];
    int row[maxnode],col[maxnode];
    int ansd,ans[maxnode];
    void init(int N,int M)
    {
        n=N,m=M;
        ansd=-1;
        for(int i=0;i<=m;i++)
        {
            U[i]=D[i]=i;
            L[i]=i-1;
            R[i]=i+1;
        }
        L[0]=m;
        R[m]=0;
        size=m;
        memset(S,0,sizeof(S));
        memset(H,-1,sizeof(H));
    }
    void Link(int r,int c)
    {
        ++S[col[++size]=c];
        row[size]=r;
        D[size]=D[c];
        U[D[c]]=size;
        U[size]=c;
        D[c]=size;
        if(H[r]<0)H[r]=L[size]=R[size]=size;
        else
        {
            R[size]=R[H[r]];
            L[R[H[r]]]=size;
            L[size]=H[r];
            R[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 restore(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]]=D[U[j]]=j;
                ++S[col[j]];
            }
        }
        L[R[c]]=R[L[c]]=c;
    }
    bool Dance(int d)
    {
        if(R[0]==0)
        {
            ansd=d;
            return true;
        }
        int c=R[0];
        for(int i=R[0];i;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 true;
            for(int j=L[i];j!=i;j=L[j])restore(col[j]);
        }
        restore(c);
        return false;
    }
}dlx;
int encode(int a,int b,int c)
{
    return a*256+b*16+c+1;//加2是为了保证,DLX中行编号是从1开始
}
void decode(int code,int &a,int &b,int &c)
{
    code--;
    c=code%16;code/=16;
    b=code%16;code/=16;
    a=code;
}
int main()
{
    bool first=true;
    while(scanf("%s",s[0])!=EOF)
    {
        if(first)first=false;
        else printf("\n");
        for(int i=1;i<16;i++)
            scanf("%s",s[i]);
        dlx.init(16*16*16,16*16*4);
        for(int r=0;r<16;r++)
            for(int c=0;c<16;c++)
            for(int v=0;v<16;v++)
            if(s[r][c]=='-'||s[r][c]=='A'+v)
            {
                int row=encode(r,c,v);
                dlx.Link(row,encode(SLOT,r,c));
                dlx.Link(row,encode(ROW,r,v));
                dlx.Link(row,encode(COL,c,v));
                dlx.Link(row,encode(SUB,(r/4)*4+c/4,v));
            }
        dlx.Dance(0);
        for(int i=0;i<dlx.ansd;i++)
        {
            int r,c,v;
            decode(dlx.ans[i],r,c,v);
            s[r][c]='A'+v;
        }
        for(int i=0;i<16;i++)
            printf("%s\n",s[i]);
    }
    return 0;
}


Language:
Sudoku
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 8302 Accepted: 2928

Description

In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example,

.2738..1.
.1...6735
.......29
3.5692.8.
.........
.6.1745.3
64.......
9518...7.
.8..6534.

Given some of the numbers in the grid, your goal is to determine the remaining numbers such that the numbers 1 through 9 appear exactly once in (1) each of nine 3 × 3 subgrids, (2) each of the nine rows, and (3) each of the nine columns.

Input

The input test file will contain multiple cases. Each test case consists of a single line containing 81 characters, which represent the 81 squares of the Sudoku grid, given one row at a time. Each character is either a digit (from 1 to 9) or a period (used to indicate an unfilled square). You may assume that each puzzle in the input will have exactly one solution. The end-of-file is denoted by a single line containing the word “end”.

Output

For each test case, print a line representing the completed Sudoku puzzle.

Sample Input

.2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.
......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
end

Sample Output

527389416819426735436751829375692184194538267268174593643217958951843672782965341
416837529982465371735129468571298643293746185864351297647913852359682714128574936


下面是9*9的,注意他们之间细微的差别

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=9*9*9+10;
const int maxm=9*9*4+10;
const int maxnode=maxn*maxm;
const int SIGMA_SIZE=9;
const int SLOT=0;
const int ROW=1;
const int COL=2;
const int SUB=3;
char s[90];

struct DLX
{
    int n,m,size;
    int U[maxnode],D[maxnode],L[maxnode],R[maxnode];
    int H[maxn],S[maxm];
    int row[maxnode],col[maxnode];
    int ansd,ans[maxnode];
    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;
        }
        L[0]=m;
        R[m]=0;
        size=m;
        memset(S,0,sizeof(S));
        memset(H,-1,sizeof(H));
    }
    void Link(int r,int c)
    {
        ++S[col[++size]=c];
        row[size]=r;
        D[size]=D[c];
        U[D[c]]=size;
        U[size]=c;
        D[c]=size;
        if(H[r]<0)H[r]=L[size]=R[size]=size;
        else
        {
            R[size]=R[H[r]];
            L[R[H[r]]]=size;
            L[size]=H[r];
            R[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 restore(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]]=D[U[j]]=j;
                ++S[col[j]];
            }
        }
        L[R[c]]=R[L[c]]=c;
    }
    bool Dance(int d)
    {
        if(R[0]==0)
        {
            ansd=d;
            return true;
        }
        int c=R[0];
        for(int i=R[0];i;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 true;
            for(int j=L[i];j!=i;j=L[j])restore(col[j]);
        }
        restore(c);
        return false;
    }
}dlx;
int encode(int a,int b,int c)
{
    return a*81+b*9+c;
}
void decode(int code,int &a,int &b,int &c)
{
    code--;
    c=code%9;code/=9;
    b=code%9;code/=9;
    a=code;
}
int main()
{
    while(scanf("%s",s)!=EOF)
    {
        if(!strcmp(s,"end"))break;
        dlx.init(9*9*9,9*9*4);
        for(int r=0;r<SIGMA_SIZE;r++)
            for(int c=0;c<SIGMA_SIZE;c++)
            for(int v=1;v<=SIGMA_SIZE;v++)
            if(s[r*9+c]=='.'||s[r*9+c]=='0'+v)
            {
                int row=encode(r,c,v);
                dlx.Link(row,encode(SLOT,r,c)+1);
                dlx.Link(row,encode(ROW,r,v));
                dlx.Link(row,encode(COL,c,v));
                dlx.Link(row,encode(SUB,(r/3)*3+c/3,v));
            }
        dlx.Dance(0);
        for(int i=0;i<dlx.ansd;i++)
        {
            int r,c,v;
            decode(dlx.ans[i],r,c,v);
            s[r*9+c]='1'+v;
        }
        printf("%s\n",s);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值