I'm going to dance 数独问题 poj 3076

来源:互联网 发布:python buffer 编辑:程序博客网 时间:2024/05/20 08:23

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+s0end;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 endend;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 endend;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;writelnend;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 getoutend;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 endend;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 endend;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 endend;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:=maxend;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 endend;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 getoutend;begin readln(tt); for tt:=1 to tt do initend.


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;}