【poj3074】【DLX】sudoku

3 篇文章 0 订阅

就是数独

Sudoku

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 9617 Accepted: 3473

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 8 . . . 7 .
. 8 . . 6 5 3 4 .
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

Source

Stanford Local 2006

又是舞蹈链,超快的。
做法什么的可以去看我上面一篇数独的题,这里就直接放代码了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<stack>
#define INF 2100000000
#define ll long long
#define clr(x)  memset(x,0,sizeof(x));
#define M 325

using namespace std;

struct link2
{
    link2 *up,*down,*right,*left,*col;
    int row,count,lie;
}*head,*c[M],*lik[5*M],dizhi[5*M];

int T,a[90],ans[M],sta,n,Ans;

int get_num(int a)
{
    int x=((a-1)/9)+1,y=((a-1)%9)+1;
    int m1=min(x-1,9-x),m2=min(y-1,9-y),mi=min(m1,m2);
    return mi+6;
}

void remove(link2 *C)
{
    C->left->right=C->right;
    C->right->left=C->left;

    link2 *i=C->down;
    while(i!=C)
    {
        link2 *j=i->right;
        while(j!=i)
        {
            j->up->down=j->down;
            j->down->up=j->up;
            j=j->right;
            j->col->count--;
        }
        i=i->down;
    }
}

void resume(link2 *C)
{
    C->left->right=C;
    C->right->left=C;

    link2 *i=C->down;
    while(i!=C)
    {
        link2 *j=i->right;
        while(j!=i)
        {
            j->up->down=j;
            j->down->up=j;
            j=j->right;
            j->col->count++;
        }
        i=i->down;
    }
}

int t;

void addline(int *index,int row)
{
    for(int i=1;i<=4;i++)
    {
        t++;
        lik[t]=&dizhi[t+T];
        if(i==1)
        {
            lik[t]->left=lik[t];
            lik[t]->right=lik[t];
        }
        else
        {
            lik[t]->left=lik[t-1];
            lik[t]->right=lik[t-1]->right;
            lik[t-1]->right->left=lik[t];
            lik[t-1]->right=lik[t];
        }
        int j=index[i];
        c[j]->count++;
        lik[t]->up=c[j]->up;
        c[j]->up->down=lik[t];
        lik[t]->down=c[j];
        c[j]->up=lik[t];
        lik[t]->col=c[j];
        lik[t]->row=row;
        lik[t]->lie=j;
    }
}

void bulid()
{
    int m=324;
    head=&dizhi[T++];
    for(int i=1;i<=m;i++)c[i]=&dizhi[T++];
    head->right=c[1];
    head->left=c[m];
    for(int i=1;i<=m;i++)
    {
        c[i]->left=i==1?head:c[i-1];
        c[i]->right=i==m?head:c[i+1];
        c[i]->up=c[i]->down=c[i];
        c[i]->count=0;
        c[i]->lie=i;
    }
    for(int i=1;i<=81;i++)
    {
        if(!a[i])continue;
        int y=(i-1)/9+1,x=(i-1)%9+1;
        int p1=i,p2=81+(y-1)*9+a[i];
        int p3=162+(x-1)*9+a[i],p4=243+((y-1)/3*3+(x-1)/3)*9+a[i];
        c[p1]->count=c[p2]->count=c[p3]->count=c[p4]->count=-1;
        c[p1]->left->right=c[p1]->right;c[p1]->right->left=c[p1]->left;
        c[p2]->left->right=c[p2]->right;c[p2]->right->left=c[p2]->left;
        c[p3]->left->right=c[p3]->right;c[p3]->right->left=c[p3]->left;
        c[p4]->left->right=c[p4]->right;c[p4]->right->left=c[p4]->left;
    }

    for(int i=1;i<=9;i++)
        for(int j=1;j<=9;j++)
            for(int k=1;k<=9;k++)
            {
                if(a[(i-1)*9+j])continue;
                int p1=(i-1)*9+j;
                int p2=81+(i-1)*9+k;
                int p3=162+(j-1)*9+k;
                int p4=243+((i-1)/3*3+(j-1)/3)*9+k;
                if(c[p1]->count==-1||c[p2]->count==-1||c[p3]->count==-1||c[p4]->count==-1)continue;
                int index[5]={0,p1,p2,p3,p4};
                addline(index,((i-1)*9+j)*10+k);
            }
}

bool dance(int x)
{
    if(head->right==head)
    {
        for(int i=1;i<=sta;i++)
            a[ans[i]/10]=ans[i]%10;
        //printf("%d:\n",n+1);
        for(int i=1;i<=81;i++)
        {
            printf("%d",a[i]);
        }

        cout<<'\n';
        return 1;
    }
    link2 *i=head->right->right;
    link2 *temp=head->right;
    while(i!=head)
    {
        if(i->count<temp->count)
            temp=i;
        i=i->right;
    }
    if(temp->down==temp)return 0;
    remove(temp);
    i=temp->down;
    while(i!=temp)
    {
        link2 *j=i->right;
        ans[++sta]=i->row;
        while(j!=i)
        {
            remove(j->col);
            j=j->right;
        }
        if(dance(x+1))return 1;
        j=i->left;
        while(j!=i)
        {
            resume(j->col);
            j=j->left;
        }
        ans[sta]=0;
        sta--;
        i=i->down;
    }
    resume(temp);
    return 0;
}

int main()
{
    freopen("in.txt","r",stdin);
    while(1)
    {
        char c;
        for(int i=1;i<=81;i++)
        {
            c=getchar();
            if(c!='.'&&(c>'9'||c<'0'))return 0;
            if(c=='.')a[i]=0;
            else a[i]=c-'0';    
        }
        c=getchar();
        t=T=0;
        clr(ans);sta=0;
        bulid();
        dance(0);

    }
}

大概就是这个样子,如果有什么问题,或错误,请在评论区提出,谢谢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值