Dancing Links,跳动的舞者,的确是很飘的一种数据结构。
DL是双向循环十字链表,其作用大体就是对精确覆盖算法的一种优化,在递归搜索的过程中利用链表容易删增的特性提高了精确覆盖算法的效率。
强烈推一篇博客,讲述的很详细,弱就不多说了。
http://www.cnblogs.com/grenet/p/3145800.html
模板贴起来,自己写的有点挫。以最经典的9*9数独为例。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#pragma comment(linker, "/STACK:1024000000")
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 0x3f3f3f3f
#define Mod 100007
using namespace std;
const int MAXCLOUM = 9*9*4+10,MAXROW = 9*9*9+10,MAXPOINT = MAXROW*4 + MAXCLOUM;
int sta[MAXROW],sta_anw;//答案栈以及栈内元素个数
int SIZE[MAXCLOUM];//每一列元素个数,不包括虚拟列指针
int PRE[MAXROW];//每一行最后加入的元素位置,初始为-1.
int C[MAXCLOUM];//每一列的头指针的位置
int ROW[MAXPOINT],COL[MAXPOINT];//每个元素的行列坐标
int L[MAXPOINT],R[MAXPOINT],U[MAXPOINT],D[MAXPOINT];//每个元素的四个指针
int Top;//第一个未分配元素的地址
int Creat(int row = -1,int col = -1)
{
ROW[Top] = row;
COL[Top] = col;
U[Top] = Top;
D[Top] = Top;
L[Top] = Top;
R[Top] = Top;
return Top++;
}
void Init(int row,int col)
{
sta_anw = 0;
Top = 0;
C[0] = Creat(-1,0);
for(int i = 1; i <= col; ++i)
{
C[i] = Creat(-1,i);
R[C[i]] = R[C[i-1]];
L[R[C[i-1]]] = C[i];
R[C[i-1]] = C[i];
L[C[i]] = C[i-1];
SIZE[i] = 0;
}
memset(PRE,-1,sizeof(PRE));
}
void Insert(int row,int col)
{
int now = Creat(row,col);
D[U[C[col]]] = now;
U[now] = U[C[col]];
D[now] = C[col];
U[C[col]] = now;
++SIZE[col];
if(PRE[row] != -1)
{
L[R[PRE[row]]] = now;
R[now] = R[PRE[row]];
L[now] = PRE[row];
R[PRE[row]] = now;
}
PRE[row] = now;
}
void Remove(int c)
{
R[L[c]] = R[c];
L[R[c]] = L[c];
int i,j;
for(i = D[c]; i != c; i = D[i])
{
for(j = R[i]; j != i ; j = R[j])
{
U[D[j]] = U[j],D[U[j]] = D[j];
--SIZE[COL[j]];
}
}
}
void Resume(int c)
{
int i,j;
for(i = U[c]; i != c; i = U[i])
{
for(j = L[i]; j != i; j = L[j])
{
U[D[j]] = j,D[U[j]] = j;
++SIZE[COL[j]];
}
}
R[L[c]] = c;
L[R[c]] = c;
}
bool Dance()
{
int now,i,j;
if(R[C[0]] == C[0])
return true;
now = R[C[0]];
for(i = now;i != C[0];i = R[i])
if(SIZE[COL[i]] < SIZE[COL[now]])
now = i;
Remove(COL[now]);
for(i = D[now]; i != now; i = D[i])
{
for(j = R[i]; j != i; j = R[j])
Remove(C[COL[j]]);
sta[sta_anw++] = ROW[i];
if(Dance())
return true;
sta_anw--;
for(j = L[i]; j != i; j = L[j])
Resume(C[COL[j]]);
}
Resume(COL[now]);
return false;
}
int num[10][10];
struct N
{
int x,y,info;
}st[1000];
inline int CalPos(int x,int y)
{
x = (x-1)/3 + 1;
y = (y-1)/3 + 1;
return (x-1)*3 + y;
}
int main()
{
int T;
bool bla = false;
scanf("%d",&T);
int ans,i,j,k;
while(T--)
{
if(bla == false)
bla = true;
else
puts("");
for(i = 1;i <= 9; ++i)
{
for(j = 1;j <= 9; ++j)
scanf("%1d",&num[i][j]);
}
Init(9*9*9,9*9*4);
ans = 1;
for(i = 1;i <= 9; ++i)
{
for(j = 1;j <= 9; ++j)
{
for(k = 1;k <= 9; ++k)
{
if(num[i][j] == 0 || num[i][j] == k)
{
Insert(ans,(i-1)*9+k);
Insert(ans,81 + (j-1)*9+k);
Insert(ans,162 + (CalPos(i,j)-1)*9 + k);
Insert(ans,243 + (i-1)*9 + j);
st[ans++] = (N){i,j,k};
}
}
}
}
Dance();
if(sta_anw)
{
for(i = 0;i < sta_anw; ++i)
num[st[sta[i]].x][st[sta[i]].y] = st[sta[i]].info;
for(i = 1;i <= 9; ++i)
{
for(j = 1;j <= 9; ++j)
printf("%d",num[i][j]);
puts("");
}
}
else
{
puts("Could not complete this grid.");
}
}
return 0;
}