poj 2676 数独 Dancing-Links(DLX)

题目大意:。。。。数独还用我说么

首先一般的解法都是爆搜,爆搜的话绝对懒得做。。于是我作死去学了Dancing-Links数据结构优化的X算法,简称DLX算法

Dancing-Links虽然名字好听,但是其实实质就是双向十字链表。。但是由于调试的时候各种挂,指针还看着及其闹心(经常调试链式结构的人一定深有同感),所以只能在调试区各种加指针删指针,来回飞舞的指针,即Dancing-Links。。。

这算法的作者太有才了,不得不说。。。。

DLX算法主要解决的是精确覆盖问题,具体做法见 http://www.cnblogs.com/grenet/p/3145800.html

这里我们要把数独问题转化为精确覆盖问题

首先数独的约束条件是什么?

1.一个格子里只能放一个数

2.每行同一数字只能放一个

3.每列同一数字只能放一个

4.每个九宫格中同一数字只能放一个

于是我们每一行就有四组约束条件:

1.81列,代表这个格子中已经放了数字

2.81列,代表第i行已经放了数字j

3.81列,代表第i列已经放了数字j

4.81列,代表第i个九宫格中已经放了数字j

然后每个格子的每种填放可能作为一行加进去就可以了

记住一定要采用A*算法,不然会死!

每次选择当前拥有1最少的列进行更新,不然必死无疑

最后贴代码 我的head开在了十字链表的最下方 加行比较方便

<pre class="sh_cpp sh_sourceCode" style="background-color: white;font-size:14px; font-family: 'Courier New', Courier, monospace;"><pre name="code" class="html">#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

struct abcd *stack[4000];
int top;

struct abcd{
	abcd *l,*r,*u,*d;
	int x,y,num;
	abcd *bottom;
	abcd(abcd *L,abcd *R,abcd *U,abcd *D,int X,int Y,int Num)
	{
		l=L;if(L)L->r=this;
		r=R;if(R)R->l=this;
		u=U;if(U)U->d=this;
		d=D;if(D)D->u=this;
		x=X;y=Y;num=Num;
		bottom=d;
		if(bottom)
			bottom->x++;
	}
	void del()
	{
		if(l)l->r=r;
		if(r)r->l=l;
		if(u)u->d=d;
		if(d)d->u=u;
		if(bottom)
			bottom->x--;
		stack[++top]=this;
	}
	void restore()
	{
		if(l)l->r=this;
		if(r)r->l=this;
		if(u)u->d=this;
		if(d)d->u=this;
		if(bottom)
			bottom->x++;
	}
}*head,*heads[400];
int m,n,map[9][9];
bool flag;
void del_column(int pos)
{
	abcd *temp1,*temp2;
	for(temp1=heads[pos]->u;temp1;temp1=temp1->u)
	{
		for(temp2=temp1->l;temp2;temp2=temp2->l)
			temp2->del();
		for(temp2=temp1->r;temp2;temp2=temp2->r)
			temp2->del();
		temp1->del();
	}
	heads[pos]->del();
}
inline void output()
{
	int i,j;
	for(i=0;i<9;i++)
	{
		for(j=0;j<9;j++)
			putchar(map[i][j]+'0');
		putchar('\n');
	}
}
void DLX()
{
	if(!head->r)
	{
		output();
		flag=1;
		return ;
	}
	int bottom=top,minnum=0x7fffffff;
	abcd *temp,*mintemp;
	for(temp=head->r;temp;temp=temp->r)
		if(temp->x<minnum)
			minnum=temp->x,mintemp=temp;
	for(temp=mintemp->u;temp;temp=temp->u)
	{
		int x=temp->x,y=temp->y,num=temp->num;
		map[x][y]=num;

		del_column(x*9+y+1			      );
		del_column(81+x*9+num		      );
		del_column(162+y*9+num	    	  );
		del_column(243+(x/3*3+y/3)*9+num  );

		DLX();
		if(flag)
			return ;
		while(top!=bottom)
			stack[top--]->restore();
	}
}
void add(int x,int y,int num)
{
	abcd *last=0x0,*temp;
	temp=heads[x*9+y+1		    	  ],last=new abcd(last,0x0,temp->u,temp,x,y,num);
	temp=heads[81+x*9+num		      ],last=new abcd(last,0x0,temp->u,temp,x,y,num);
	temp=heads[162+y*9+num		      ],last=new abcd(last,0x0,temp->u,temp,x,y,num);
	temp=heads[243+(x/3*3+y/3)*9+num  ],last=new abcd(last,0x0,temp->u,temp,x,y,num);
}
int main()
{
	int T,i,j,k,x;
	abcd *temp,*last;

	//freopen("sudoku.in","r",stdin);
	//freopen("sudoku.out","w",stdout);

	for(cin>>T;T;T--)
	{
		head=new abcd(0x0,0x0,0x0,0x0,0,0,0);top=0;flag=0;
		for(i=1,last=head;i<=81*4;i++)
			last=new abcd(last,0x0,0x0,0x0,0,0,i),heads[i]=last;
		for(i=0;i<9;i++)
			for(j=0;j<9;j++)
				scanf("%1d",&map[i][j]);
		for(i=0;i<9;i++)
			for(j=0;j<9;j++)
				if(map[i][j])
					add(i,j,map[i][j]);
				else
					for(k=1;k<=9;k++)
						add(i,j,k);
		DLX();
	}
}

				
时间: 2024-09-29 00:51:08

poj 2676 数独 Dancing-Links(DLX)的相关文章

poj 3074 Sudoku(Dancing Links)

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 . . .

POJ 3076 Sudoku (dancing links)

题目大意: 16*16的数独. 思路分析: 多说无益. 想说的就是dancing links 的行是按照 第一行第一列填 1 第一行第二列填 2 -- 第一行第十五列填15 第一行第二列填 1 -- 第二行.... 列的纺织则是 第一行放1,第一行放2,..第十六行放16...第一列放1..第一列放2...第十六列放16..第一块区域放1 ....然后在最后81位就是放自己的位置,准确的说就是 r*m+c. #include <cstdio> #include <iostream>

POJ 2676 数独(DFS)

Sudoku Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 21612   Accepted: 10274   Special Judge Description Sudoku is a very simple task. A square table with 9 rows and 9 columns is divided to 9 smaller squares 3x3 as shown on the Figure.

POJ 2676 数独

题意: 给你一个9*9的未完成的数独,将其填完 思路: 暴搜 从第一个位置搜起,有数字就直接跳过搜下一个位置,没数字就填数字 .通过行,列,九宫格不能重复填数,把能填的数填进去就可以了 //By DXY 2018.04.27 #include<iostream> #include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm>

POJ 2676 Sudoku (搜索,Dancing Links)

题目: http://poj.org/problem?id=2676 题意: 数独,每行1-9,每列1-9,每3*3小格1-9,填数,不能重复 方法:Dancing Links(16ms)或者DFS暴搜(400-900ms) Dancing Links(DLX) 是为了解决矩阵精确覆盖问题的算法,算法效率非常高 使用DLX解决的问题必须转化为矩阵精确覆盖问题: 1.DLX详解: http://wenku.baidu.com/view/d8f13dc45fbfc77da269b126.html 2

Dancing Links 小结 (因为之前丢了一次稿,未完待续)

Dancing Links (DLX)是Knuth为了解决精确覆盖问题而提出的算法,很多搜索问题可以转化位精确覆盖问题从而使用Dancing Links解决(效率会比DFS高很多,因为里面常常蕴涵着意想不到的剪枝) 信息学竞赛中的DLX的问题类似网络流,只需建图+贴版即可 参考文献: 1.DLX的原理:Knuth的论文: 原版:http://arxiv.org/abs/cs/0011047 翻译版:http://wenku.baidu.com/view/d8f13dc45fbfc77da269b

HDU 1426 dancing links解决数独问题

题目大意: 这是一个最简单的数独填充题目,题目保证只能产生一种数独,所以这里的初始9宫格较为稠密,可以直接dfs也没有问题 但最近练习dancing links,这类数据结构解决数独无疑效率会高很多 dancing links的数独限制条件是: 1.每行有9个元素,共9行 对应dlx81列 2.每列有9个元素,共9行 对应dlx81列 3.每个九宫格有9个元素,共9行 对应dlx81列 4.81个格子,每个格子最多有一个数 1 #include <iostream> 2 #include &l

hihoCoder #1321 : 搜索五?数独 (Dancing Links ,精确覆盖)

hiho一下第102周的题目. 原题地址:http://hihocoder.com/problemset/problem/1321 题意:输入一个9*9数独矩阵,0表示没填的空位,输出这个数独的答案. 提示已经讲解的很清楚了.稍微整理下思路.最后附AC代码. 一.Dancing Links解决精确覆盖问题.      1.精确覆盖问题         给定一个n行,m列的01矩阵.从中选择若干行使得每一列有且恰好只有一个1. 例如: 答案是选择2,3,4行. 2.DancingLinks求解精确

POJ 2676 数码问题DLX

Sudoku Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13023   Accepted: 6455   Special Judge Description Sudoku is a very simple task. A square table with 9 rows and 9 columns is divided to 9 smaller squares 3x3 as shown on the Figure.