poj 3074 Sudoku(Dancing Links)
Sudoku
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 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. Sample Output 527389416819426735436751829375692184194538267268174593643217958951843672782965341 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;
}
版权声明:本文博主原创文章。博客,未经同意不得转载。
poj 3074 Sudoku(Dancing Links)的更多相关文章
- POJ 3074 Sudoku (Dacing Links)
推荐一个写数独很好的博客:http://www.cnblogs.com/grenet/p/3163550.html 主要是把九宫格里的元素换到矩阵里面再求解dancing links 网上找的一模版 ...
- POJ 3076 Sudoku (dancing links)
题目大意: 16*16的数独. 思路分析: 多说无益. 想说的就是dancing links 的行是依照 第一行第一列填 1 第一行第二列填 2 -- 第一行第十五列填15 第一行第二列填 1 -- ...
- POJ 3074 Sudoku (Dancing Links)
传送门:http://poj.org/problem?id=3074 DLX 数独的9*9的模板题. 具体建模详见下面这篇论文.其中9*9的数独怎么转化到精确覆盖问题,以及相关矩阵行列的定义都在下文中 ...
- POJ 3074 Sudoku (DLX)
Sudoku Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit Statu ...
- POJ3074 Sudoku —— Dancing Links 精确覆盖
题目链接:http://poj.org/problem?id=3074 Sudoku Time Limit: 1000MS Memory Limit: 65536K Total Submissio ...
- POJ 3074 Sudoku DLX精确覆盖
DLX精确覆盖.....模版题 Sudoku Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8336 Accepted: ...
- (简单) POJ 3074 Sudoku, DLX+精确覆盖。
Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgr ...
- POJ - 3074 Sudoku (搜索)剪枝+位运算优化
In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For exa ...
- POJ 3074 Sudoku(算竞进阶习题)
二进制优化+dfs 话说这题数据中真的丧心病狂..不加inline还过不去.. 因为不会DLX只好用二进制来优化了...万万没想到还是低空飘过 我们在行.列.格分别用一个9位二进制常数来记录什么数能放 ...
随机推荐
- Spark简述及基本架构
Spark简述 Spark发源于美国加州大学伯克利分校AMPLab的集群计算平台.它立足 于内存计算.从多迭代批量处理出发,兼收并蓄数据仓库.流处理和图计算等多种计算范式. 特点: 1.轻 Spark ...
- Linux源文件夹结构呈现
1.arch文件夹: - 相关的存储在不同平台上的代码,每个平台都采用了不同的文件夹来区分. ******Alpha平台 ******Arm平台 ******Arv32平台 ******X86平台 2 ...
- Java中WebService实例
Web Services是由企业公布的完毕其特定商务需求的在线应用服务,其它公司或应用软件可以通过Internet来訪问并使用这项在线服务. Web Service的关键技术和规则: 1.XML:描写 ...
- MVC之Session State性能
ASP.NET MVC之Session State性能问题(七) 前言 这一节翻译一篇有关Session State性能问题的文章,非一字一句翻译. 话题 不知道我们在真实环境中是否用到了Sess ...
- 读懂Java中的Socket编程(转)
Socket,又称为套接字,Socket是计算机网络通信的基本的技术之一.如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的.本文会介绍一下基于TCP/IP的S ...
- Android_多媒体_SoundPool声音池使用
1.SoundPool概述 SoundPool就相当于一个简单的集合,可以将apk中的资源或者系统中的文件加载至内存中,使用了MediaPlayer服务区解码音频文件,用SoundPool可以播一些短 ...
- Oracle数据库案例整理-Oracle系统执行时故障-Shared Pool内存不足导致数据库响应缓慢
1.1 现象描写叙述 数据库节点响应缓慢,部分用户业务受到影响. 查看数据库告警日志,開始显示ORA-07445错误,然后是大量的ORA-04031错误和ORA-00600错误. 检查数据 ...
- 每天进步一点点——Linux磁盘管理LVM与RAID
转载请注明出处:http://blog.csdn.net/cywosp/article/details/38965799 1. 传统磁盘管理问题 当分区大小不够用时无法扩展其大小,仅仅能通过加入硬盘. ...
- POJ 2948 DP
一个row*col的矩阵,每一个格子内有两种矿yeyenum和bloggium,而且知道它们在每一个格子内的数量是多少.最北边有bloggium的收集站,最西边有 yeyenum 的收集站.如今要在这 ...
- SQL语句查询数据库的触发器、存储过程、视图以及表的SQL语句
Sql Server数据库用SQL语句查询方法如下: select name from sysobjects where xtype='TR' --所有触发器 select name from sys ...