poj 3074 Sudoku(Dancing Links)

poj 3074 Sudoku(Dancing Links)

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

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,

. 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

题意

就是经典的数独问题。

思路:

搜索。

可是得借助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了。

具体见代码:

#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.net/116883.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Vue学习之按键修饰符

    Vue学习之按键修饰符Vue学习之按键修饰符

    2022年4月23日
    73
  • springboot框架的理解_谈谈你对springmvc的理解

    springboot框架的理解_谈谈你对springmvc的理解1.起源SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。用我的话来理解,就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像Maven整合了所有的Jar包,SpringBoot整合了所有的框…

    2022年8月20日
    3
  • MySQL导入sql文件的三种方法

    MySQL导入sql文件的三种方法文章目录一、使用工具NavicatforMySQL导入1.打开localhost_3306,选中右击“新建数据库”3.指定数据库名和字符集(可根据sql文件的字符集类型自行选择)3.选中数据库下的表运行SQL文件4.选中路径导入二、使用MySQLWorkbench导入(MySQL的官方工具)1、第一种方法①.新建一个数据库demo(名字任取),点击指示图标(或者File栏里面的OpenSQLScript…)②.选中路径导入SQL文件③.添加指定库名的命令,并点击运行注意:大概在15、16行

    2022年10月2日
    1
  • QQ浏览器谷歌版吾爱破解(QQ浏览器最新谷歌版)

    ubuntu软件安装大全本文基于ubuntu16.04系统本文提供下载地址:安装包地址:https://github.com/weiguow/ubuntu-software.gitdeepin-wine地址:https://github.com/weiguow/deepin-wine-ubuntu.git1.Chrome浏览器sudowgethttps://repo.fdzh.o…

    2022年4月15日
    136
  • 来自damon的zencart二次开发教程-3.2复制模板(仿站)操作教程「建议收藏」

    来自damon的zencart二次开发教程-3.2复制模板(仿站)操作教程「建议收藏」用zencart来复制别人的网站成本低,效率高。前面我发了一篇有关开发自己的zencat模板的文章(《来自damon的zencart二次开发教程-3.1开发自己的zencart模板》),里面只有一些基础的理论,下面,我们就来实际操作一下。1.利用离线浏览器将(《离线浏览器Teleport_Pro完全教程与安装文件下载》)你的目标网页文件(图片,html以及css样式表,j…

    2022年9月7日
    0
  • android之存储篇_SharedPreferences存储方式

    SharedPreferences是一种轻型的数据存储方式,它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息。其存储位置在/data/data//shared_prefs目录下。SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现。实现SharedPreferences存储的步骤如下:  一、根据C

    2022年3月10日
    599

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号