前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >poj 3074 Sudoku(Dancing Links)

poj 3074 Sudoku(Dancing Links)

作者头像
全栈程序员站长
发布2022-07-06 17:38:11
3320
发布2022-07-06 17:38:11
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是全栈君

Sudoku

Time Limit: 1000MS

Memory Limit: 65536K

Total Submissions: 8152

Accepted: 2862

Description

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

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

代码语言:javascript
复制
.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

代码语言:javascript
复制
527389416819426735436751829375692184194538267268174593643217958951843672782965341
416837529982465371735129468571298643293746185864351297647913852359682714128574936

Source

Stanford Local 2006

题意:

就是经典的数独问题。

思路:

搜索。

可是得借助Dancing Links加速。关键就在于如何把数独问题抽象成一个精确覆盖问题了。

我们首先考虑数独的游戏规则。

1.每一个格子都必须填一个数字。

2.每一行1-9这几个数字都必须出现一次。

3.每一列1-9这几个数字都必须出现一次。

4.每一宫格1-9这几个数字都必须出现一次。

我们知道Dancing Links的精确覆盖智能处理0,1的序列覆盖每一列为一个约束条件。

那么我们就必须把上述约束转换成0,1矩阵。

对于1。

我们用第(i-1)*9+j列为1表示i行j列的已经填数。一共占用81列。

对于2.我们用81+(i-1)*9+v列表示第i行已经有v这个值。一共占用81列。

对于3.我们用162+(j-1)*9+v列表示第j列已经有v这个值。一共占用81列。

对于3.我们用243+(3*((i-1)/3)+(j+2)/3-1)+v列表示第3*((i-1)/3)+(j+2)/3宫格已经有v这个值。一共占用81列。

ps:i,j都从1開始。3*((i-1)/3)+(j+2)/3为通过i,j确定的宫格数。

这样就会为每一个宫格确定一个01序列约束。

然后建好矩阵后。

套上精确覆盖模板后就ok了。

具体见代码:

代码语言:javascript
复制
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int INF=0x3f3f3f3f;const int maxn=3645;//每一个格子可能有9个取值。
所以最多有81*9行。然后243列。

int U[maxn],D[maxn],L[maxn],R[maxn],C[maxn],row[maxn];//上下左右指针。c[i]结点i相应的列。row[i]结点i相应的行号。

int S[350],H[800],ans[100];//S[i]为i列1的个数。

H[i]为i行的尾指针。

int n,m,cnt,deep;struct node{    int x,y,v;} st[maxn];char maze[150],path[150];void init(){    int i;    for(i=1;i<=800;i++)        H[i]=-1;    for(i=0;i<=324;i++)    {         S[i]=0;         L[i+1]=i;         R[i]=i+1;         U[i]=D[i]=i;    }    R[324]=deep=0;    cnt=325;}void Insert(int r,int c){                        //头插法建链表    U[cnt]=c,D[cnt]=D[c];//确定新增结点上下指针信息    U[D[c]]=cnt,D[c]=cnt;//恢复链表信息    if(H[r]==-1)         //确定左右指针信息        H[r]=L[cnt]=R[cnt]=cnt;//增加头    else    {        L[cnt]=H[r],R[cnt]=R[H[r]];//头插法        L[R[H[r]]]=cnt,R[H[r]]=cnt;    }    S[c]++;//更新附加信息    row[cnt]=r;    C[cnt++]=c;}void Remove(int c)//移除c列。{    int i,j;    R[L[c]]=R[c],L[R[c]]=L[c];    for(i=D[c];i!=c;i=D[i])        for(j=R[i];j!=i;j=R[j])            D[U[j]]=D[j],U[D[j]]=U[j],S[C[j]]--;}void Resume(int c)//还原c列。{    int i,j;    R[L[c]]=L[R[c]]=c;    for(i=D[c];i!=c;i=D[i])        for(j=R[i];j!=i;j=R[j])            D[U[j]]=U[D[j]]=j,S[C[j]]++;}bool dfs(){    if(R[0]==0)        return true;    int i,j,c,miv=INF;    for(i=R[0];i;i=R[i])        if(S[i]<miv)            miv=S[i],c=i;    Remove(c);//处理第c列    for(i=D[c];i!=c;i=D[i])    {        for(j=R[i];j!=i;j=R[j])            Remove(C[j]);        ans[deep++]=row[i];        if(dfs())            return true;        for(j=L[i];j!=i;j=L[j])            Resume(C[j]);        deep--;    }    Resume(c);    return false;}int main(){    int i,j,v,r,p;    while(gets(maze))    {        if(maze[0]=='e')            break;        init();        r=1;        for(i=1;i<=9;i++)//每行为一个格子的一种选择。

        {            for(j=1;j<=9;j++)            {                if(maze[(i-1)*9+j-1]=='.')                {                    for(v=1;v<=9;v++)                    {                        Insert(r,(i-1)*9+j);                        Insert(r,81+(i-1)*9+v);                        Insert(r,162+(j-1)*9+v);                        Insert(r,243+(((i-1)/3)*3+(j+2)/3-1)*9+v);                        st[r].x=i,st[r].y=j,st[r].v=v;                        r++;                    }                }                else                {                    v=maze[(i-1)*9+j-1]-'0';                    Insert(r,(i-1)*9+j);                    Insert(r,81+(i-1)*9+v);                    Insert(r,162+(j-1)*9+v);                    Insert(r,243+(((i-1)/3)*3+(j+2)/3-1)*9+v);                    st[r].x=i,st[r].y=j,st[r].v=v;                    r++;                }            }        }        dfs();        for(i=0;i<deep;i++)        {            p=ans[i];            path[(st[p].x-1)*9+st[p].y-1]='0'+st[p].v;        }        path[deep]=0;        printf("%s\n",path);    }    return 0;}

版权声明:本文博主原创文章。博客,未经同意不得转载。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/116883.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年1月1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档