dancing link的应用,很奇葩的遇到了传说中的PE
16*16的数独问题,dlx即可解决,惊奇的发现高二的师兄们雄踞了pascal的第一版,同样是dancing link,我的速度却只能退居第二版。
转换模型——>精确覆盖
数独问题中每个元素,每行只出现一次,每列只出现一次,每宫只出现一次,每格只出现一个元素,联想到0,1精确覆盖,建立矩阵
分为(16+16+16)*16+16*16,前三个16分别表示行,列,宫,*16表示有16种选择,后16*16表示16*16个格子。
例如第一行,第一列,已知填1号元素,则在描述这个元素的那一行,表示第一行填1号元素的位置放一,表示第一列填1号元素位置放一,表示第一宫填1号元素位置放一,表示第一行第一列放了元素的位置放一。
而对于未知的格子,则有16种可能,所以描述这个元素要分16行。
接下来就跳舞吧。
const g:array[1..16,1..16]of integer=
((1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4),
(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4),
(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4),
(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4),
(5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8),
(5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8),
(5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8),
(5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8),
(9,9,9,9,10,10,10,10,11,11,11,11,12,12,12,12),
(9,9,9,9,10,10,10,10,11,11,11,11,12,12,12,12),
(9,9,9,9,10,10,10,10,11,11,11,11,12,12,12,12),
(9,9,9,9,10,10,10,10,11,11,11,11,12,12,12,12),
(13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16),
(13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16),
(13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16),
(13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16));
var l,r,u,d,t,s,c,l1,r1:array[0..20000]of longint;
f:array[1..20000]of boolean;
ans,a:array[1..16,1..16]of char;
s0,s1,s2,s3,s4,ss:longint;
flag:boolean;
procedure origin;
var i:longint;
begin
fillchar(d,sizeof(d),0);fillchar(u,sizeof(u),0);
fillchar(r,sizeof(r),0);fillchar(l,sizeof(l),0);
fillchar(s,sizeof(s),0);fillchar(f,sizeof(f),false);
fillchar(ans,sizeof(ans),0);
s1:=16*16;s2:=s1+16*16;s3:=s2+16*16;s4:=s3+16*16;ss:=s4;
r[0]:=1;l[0]:=ss;
for i:=1 to ss do begin r[i]:=i+1;l[i]:=i-1;u[i]:=i;d[i]:=i end;
r[ss]:=0;
for i:=ss+1 to ss+s0 do begin l[i]:=i;r[i]:=i end;
ss:=ss+s0
end;
procedure link(x,y:longint);
begin
inc(ss);c[ss]:=y;t[ss]:=x;
l[ss]:=l[x];r[l[x]]:=ss;l[x]:=ss;r[ss]:=x;
u[ss]:=u[y];d[u[y]]:=ss;u[y]:=ss;d[ss]:=y;
inc(s[y])
end;
procedure ins(x,y:longint);
var i,xx:longint;
begin
for i:=1 to 16 do begin
xx:=(x-1)*16;
link(s0+i+s4,xx+i);
xx:=s1+(y-1)*16;
link(s0+i+s4,xx+i);
xx:=s2+(g[x,y]-1)*16;
link(s0+i+s4,xx+i);
xx:=s3+(x-1)*16+y;
link(s0+i+s4,xx)
end;
s0:=s0+16;
end;
procedure ins2(x,y,z:longint);
var xx:longint;
begin
xx:=(x-1)*16;
link(s0+1+s4,xx+z);
xx:=s1+(y-1)*16;
link(s0+1+s4,xx+z);
xx:=s2+(g[x,y]-1)*16;
link(s0+1+s4,xx+z);
xx:=s3+(x-1)*16+y;
link(s0+1+s4,xx);
inc(s0)
end;
procedure del(x:longint);
var i,j:longint;
begin
r[l[x]]:=r[x];l[r[x]]:=l[x];
i:=x;
while d[i]<>x do begin
i:=d[i];j:=i;
while r[j]<>i do begin
j:=r[j];
if j<>t[i] then begin
u[d[j]]:=u[j];d[u[j]]:=d[j];
dec(s[c[j]])
end
end
end
end;
procedure rel(x:longint);
var i,j:longint;
begin
r[l[x]]:=x;l[r[x]]:=x;
i:=x;
while u[i]<>x do begin
i:=u[i];j:=i;
while l[j]<>i do begin
j:=l[j];
if j<>t[i] then begin
u[d[j]]:=j;d[u[j]]:=j;
inc(s[c[j]])
end
end
end
end;
procedure dfs(k:longint);
var x,min,y,i,j:longint;
begin
if r[0]=0 then begin flag:=true;exit end;
x:=0;min:=maxlongint;y:=0;
while r[x]<>0 do begin
x:=r[x];
if s[x]<min then begin min:=s[x];y:=x end
end;
x:=y;del(x);i:=x;
while d[i]<>x do begin
i:=d[i];j:=i;f[t[i]]:=true;
while r[j]<>i do begin
j:=r[j];
if j<>t[i] then del(c[j])
end;
dfs(k+1);
if flag then exit;
j:=i;
while l[j]<>i do begin
j:=l[j];
if j<>t[i] then rel(c[j])
end;
f[t[i]]:=false
end;
rel(x)
end;
procedure getout;
var x,x1,y1,k1,i,j:longint;
begin
fillchar(ans,sizeof(ans),0);
for i:=s4+1 to s4+s0 do
if f[i] then begin
if i=1056 then
y1:=y1;
x:=r[i];
if c[x] mod 16<>0 then x1:=c[x] div 16 + 1 else x1:=c[x] div 16;
k1:=c[x] mod 16;
if k1=0 then k1:=16;
x:=r[x];
if (c[x]-s1) mod 16<>0 then y1:=(c[x]-s1) div 16 + 1 else y1:=(c[x]-s1) div 16;
ans[x1,y1]:=chr(k1+64)
end;
for i:=1 to 16 do begin
for j:=1 to 16 do
write(ans[i,j]);
writeln
end;
readln;writeln
end;
procedure init;
var i,j:longint;
begin
s0:=0;
for i:=1 to 16 do begin
for j:=1 to 16 do begin
read(a[i,j]);
if a[i,j]='-' then s0:=s0+16
else inc(s0)
end;
readln
end;
origin;
s0:=0;
for i:=1 to 16 do
for j:=1 to 16 do begin
if a[i,j]='-' then ins(i,j)
else ins2(i,j,ord(a[i,j])-64)
end;
r1:=r;l1:=l;
flag:=false;
dfs(0);
r:=r1;l:=l1;
if flag then getout
end;
begin
while not seekeof do init;
end.
对于PE,每组数据之间要空行
poj 2676
const map:array[1..9,1..9]of longint=(
(1,1,1,2,2,2,3,3,3),
(1,1,1,2,2,2,3,3,3),
(1,1,1,2,2,2,3,3,3),
(4,4,4,5,5,5,6,6,6),
(4,4,4,5,5,5,6,6,6),
(4,4,4,5,5,5,6,6,6),
(7,7,7,8,8,8,9,9,9),
(7,7,7,8,8,8,9,9,9),
(7,7,7,8,8,8,9,9,9)
);
n=9;
max=1400;
var a,t,c,l,r,u,d,s:array[0..100000]of longint;
f:array[0..100000]of boolean;
ans:array[1..9,1..9]of longint;
s1,ss,tt:longint;
flag:boolean;
procedure del(x:longint);
var i,j:longint;
begin
r[l[x]]:=r[x];l[r[x]]:=l[x];
i:=x;
while d[i]<>x do begin
i:=d[i];j:=i;
while r[j]<>i do begin
j:=r[j];
if j<>t[i] then begin
d[u[j]]:=d[j];u[d[j]]:=u[j];
dec(s[c[j]])
end
end
end
end;
procedure rel(x:longint);
var i,j:longint;
begin
r[l[x]]:=x;l[r[x]]:=x;
i:=x;
while d[i]<>x do begin
i:=d[i];j:=i;
while r[j]<>i do begin
j:=r[j];
if j<>t[i] then begin
d[u[j]]:=j;u[d[j]]:=j;
inc(s[c[j]])
end
end
end
end;
procedure dfs;
var x,y,min,i,j:longint;
begin
if r[0]=0 then begin flag:=true;exit end;
x:=0;min:=maxlongint;y:=0;
while r[x]<>0 do begin
x:=r[x];
if s[x]<min then begin min:=s[x];y:=x end
end;
if min>1073741819 then begin flag:=true;exit end;
x:=y;del(x);i:=x;
while d[i]<>x do begin
i:=d[i];j:=i;f[t[i]]:=true;
while r[j]<>i do begin
j:=r[j];
if j<>t[i] then del(c[j])
end;
dfs;
if flag then exit;
j:=i;
while r[j]<>i do begin
j:=r[j];
if j<>t[i] then rel(c[j])
end;
f[t[i]]:=false
end
end;
procedure link(x:longint);
begin
inc(ss);t[ss]:=s1;c[ss]:=x;
r[l[s1]]:=ss;l[ss]:=l[s1];l[s1]:=ss;r[ss]:=s1;
d[u[x]]:=ss;u[ss]:=u[x];u[x]:=ss;d[ss]:=x;
inc(s[x])
end;
procedure origin;
var i:longint;
begin
fillchar(d,sizeof(d),0);fillchar(u,sizeof(u),0);
fillchar(l,sizeof(l),0);fillchar(r,sizeof(r),0);
fillchar(t,sizeof(t),0);fillchar(c,sizeof(c),0);
fillchar(s,sizeof(s),0);fillchar(f,sizeof(f),false);
for i:=1 to max>>1 do begin
l[i]:=i-1;r[i]:=i+1
end;
r[max>>1]:=0;
r[0]:=1;l[0]:=max>>1;
for i:=0 to max>>1 do begin
u[i]:=i;d[i]:=i;
end;
for i:=max>>1+1 to max do begin
r[i]:=i;l[i]:=i
end;
s1:=max>>1;ss:=max
end;
procedure getout;
var i,j,x,x1,x2:longint;
begin
for i:=max>>1+1 to s1 do
if f[i] then begin
if i=1034 then
x:=x;
x:=c[l[i]];
x:=x-9*9-9*9-9*9;
x1:=(x div 9)+1;
x2:=x mod 9;
if x2=0 then begin x2:=9;dec(x1) end;
ans[x1,x2]:=a[i]
end;
for i:=1 to n do begin
for j:=1 to n do
write(ans[i,j]);
writeln
end
end;
procedure init;
var i,m,j,x,k:longint;
y:char;
begin
origin;
for i:=1 to n do begin
for j:=1 to n do begin
read(y);x:=ord(y)-48;
if x=0 then begin
for k:=1 to 9 do begin
inc(s1);a[s1]:=k;
m:=(i-1)*n;link(m+k);
m:=n*n;
link(m+(j-1)*n+k);
m:=m+m;
link(m+(map[i,j]-1)*n+k);
m:=m+n*n;
link(m+(i-1)*n+j)
end
end
else begin
inc(s1);k:=x;a[s1]:=k;
m:=(i-1)*n;link(m+k);
m:=n*n;
link(m+(j-1)*n+k);
m:=m+m;
link(m+(map[i,j]-1)*n+k);
m:=m+n*n;
link(m+(i-1)*n+j)
end
end;
readln
end;
flag:=false;
for i:=1 to max>>1 do if s[i]=0 then s[i]:=maxlongint;
dfs;
if flag then getout
end;
begin
readln(tt);
for tt:=1 to tt do init
end.
poj3076 c++版
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <cassert>
#include <set>
const int oo=1073741819;
using namespace std;
struct pp{
int l,r,w;
}P[200000];
set < int > g[5000];
int l[200000],r[200000],u[200000],d[200000],R[200000],C[200000];
int row[200000],clo[200000],id[20][20],S[200000];
bool v[200000];
int n,m,ss;
char ch[20][20],ans[20][20];
int ori()
{
++ss;
l[ss]=r[ss]=u[ss]=d[ss]=ss,R[ss]=C[ss]=0;
S[ss]=0;
return ss;
}
void linkud(int x,int y)
{
d[x]=y,u[y]=x;
}
void linklr(int x,int y)
{
r[x]=y,l[y]=x;
}
void add(int x,int y)
{
ori();
R[ss]=row[x],C[ss]=clo[y];
int last=u[clo[y]];
linkud(last,ss),linkud(ss,clo[y]);
last=l[row[x]];
linklr(last,ss),linklr(ss,row[x]);
S[C[ss]]++;
}
void build()
{
ss=0;
for (int i=1;i<=n;i++) v[i]=0;
for (int i=1;i<=n;i++) row[i]=ori();
for (int i=0;i<=m;i++) clo[i]=ori();
for (int i=1;i<n;i++) linkud(row[i],row[i+1]);
linkud(row[n],row[1]);
for (int i=0;i<m;i++) linklr(clo[i],clo[i+1]);
linklr(clo[m],clo[0]);
for (int i=1;i<=n;i++) {
set < int > :: iterator it=g[i].begin();
for (;it!=g[i].end();it++)
add(i,*it);
}
// cout<<ss<<endl;
}
void del(int x)
{
linklr(l[x],r[x]);
for (int i=x;d[i]!=x;) {
i=d[i];
for (int y=i;r[y]!=i;) {
y=r[y];
if (R[y] && C[y]) {
linkud(u[y],d[y]);
S[C[y]]--;
}
}
}
}
void rel(int x)
{
linklr(l[x],x),linklr(x,r[x]);
for (int i=x;u[i]!=x;) {
i=u[i];
for (int y=i;l[y]!=i;) {
y=l[y];
if (R[y] && C[y]) {
linkud(u[y],y),linkud(y,d[y]);
S[C[y]]++;
}
}
}
}
bool DLX(int s,int step)
{
if (r[s]==s) return 1;
int x,Min=oo,Mini=0;
for (int i=s;r[i]!=s;) {
i=r[i];
if (S[i]<Min)
Min=S[i],Mini=i;
}
x=Mini,del(x);
for (int i=x;d[i]!=x;) {
i=d[i];
for (int y=i;r[y]!=i;) {
y=r[y];
if (R[y] && C[y]) del(C[y]);
}
v[R[i]]=1;
if (DLX(s,step+1)) return 1;
v[R[i]]=0;
for (int y=i;l[y]!=i;) {
y=l[y];
if (R[y] && C[y]) rel(C[y]);
}
}
rel(x);
return 0;
}
int main() {
int tot=0;
for (int lx=1;lx<=13;lx+=4)
for (int ly=1;ly<=13;ly+=4) {
++tot;
for (int i=lx;i<=lx+3;i++)
for (int j=ly;j<=ly+3;j++) id[i][j]=tot;
}
for (;scanf("%s",ch[1]+1)==1;) {
for (int i=2;i<=16;i++) scanf("%s",ch[i]+1);
n=0,m=16*16+16*16*3;
for (int i=1;i<=16;i++)
for (int j=1;j<=16;j++)
if (ch[i][j]=='-') {
for (int k=1;k<=16;k++) {
++n,g[n].clear();
int p=(i-1)*16+j;
g[n].insert(p);
p=16*16+(i-1)*16+k;
g[n].insert(p);
p=16*16+16*16+(j-1)*16+k;
g[n].insert(p);
p=16*16+16*16*2+(id[i][j]-1)*16+k;
g[n].insert(p);
P[n].l=i,P[n].r=j,P[n].w=k+'A'-1;
}
}
else {
int k=ch[i][j]-'A'+1;
++n,g[n].clear();
int p=(i-1)*16+j;
g[n].insert(p);
p=16*16+(i-1)*16+k;
g[n].insert(p);
p=16*16+16*16+(j-1)*16+k;
g[n].insert(p);
p=16*16+16*16*2+(id[i][j]-1)*16+k;
g[n].insert(p);
P[n].l=i,P[n].r=j,P[n].w=k+'A'-1;
}
build();
// cout<<ss<<' '<<S[clo[1]]<<endl;
DLX(clo[0],0);
for (int i=1;i<=n;i++)
if (v[row[i]]) {
ans[P[i].l][P[i].r]=P[i].w;
}
for (int i=1;i<=16;i++) {
for (int j=1;j<=16;j++)
printf("%c",ans[i][j]);
printf("\n");
}
printf("\n");
}
return 0;
}