您的位置:首页 > 其它

舞动的dancing links poj 3740

2011-05-18 20:54 344 查看
对于npc问题,我们似乎只能用搜索(或状压dp)。

但是,有时候,搜索的期望得分是满分,比如说,当dancing links跳舞的时候。

dancing link 作为双向链表,拥有优秀的性质,快速的删除和恢复,任何熟练掌握链表的人都可以轻易上手,更重要的是,它为搜索省去大量回朔时间,并且方便启发式进行(只需加估价数组(代码中s)),优美的操作就像绚丽的舞步。

由于是矩阵,所以采用十字链表(up,down,left,right) c记录列号,t记录行号,s记录该列还有多少节点(尽量选择节点少进行拓展)

poj 3740(未加启发式) 219ms

var n,m,ss:longint;
    flag:boolean;
    u,d,r,l,c,t:array[0..50000]of longint;
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;
 u[ss]:=u[y];d[u[y]]:=ss;u[y]:=ss
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]
   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
   end
  end
 end
end;
procedure dfs(k:longint);
var i,j,x:longint;
begin
 if r[0]=0 then begin flag:=true;exit end;
 x:=r[0];del(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 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
 end;
 rel(x)
end;
procedure origin;
var i:longint;
begin
 fillchar(l,sizeof(l),0);fillchar(r,sizeof(r),0);
 fillchar(u,sizeof(u),0);fillchar(d,sizeof(d),0);
 fillchar(c,sizeof(c),0);fillchar(t,sizeof(t),0);
 r[0]:=1;l[0]:=m;
 for i:=1 to m do begin l[i]:=i-1;r[i]:=i+1;u[i]:=i;d[i]:=i end;
 r[m]:=0;
 for i:=m+1 to n+m do begin l[i]:=i;r[i]:=i end;
 ss:=n+m
end;
procedure init;
var i,j,x:longint;
begin
 readln(n,m);
 origin;
 for i:=1 to n do begin
  for j:=1 to m do begin
   read(x);
   if x=1 then link(i+m,j)
  end;
  readln
 end;
 for i:=1 to m do d[u[i]]:=i;
 for i:=m+1 to m+n do r[l[i]]:=i;
 flag:=false;
 dfs(0);
 if flag then writeln('Yes, I found it')
         else writeln('It is impossible')
end;
begin
 while not(seekeof) do init
end.


poj 3740(加启发式) 172ms

var n,m,ss:longint;
    flag:boolean;
    u,d,r,l,c,t:array[0..50000]of longint;
    s:array[1..300]of longint;
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;
 u[ss]:=u[y];d[u[y]]:=ss;u[y]:=ss;
 inc(s[y])
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 i,j,x,y,min: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;
  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
 end;
 rel(x)
end;
procedure origin;
var i:longint;
begin
 fillchar(l,sizeof(l),0);fillchar(r,sizeof(r),0);
 fillchar(u,sizeof(u),0);fillchar(d,sizeof(d),0);
 fillchar(c,sizeof(c),0);fillchar(t,sizeof(t),0);
 fillchar(s,sizeof(s),0);
 r[0]:=1;l[0]:=m;
 for i:=1 to m do begin l[i]:=i-1;r[i]:=i+1;u[i]:=i;d[i]:=i end;
 r[m]:=0;
 for i:=m+1 to n+m do begin l[i]:=i;r[i]:=i end;
 ss:=n+m
end;
procedure init;
var i,j,x:longint;
begin
 readln(n,m);
 origin;
 for i:=1 to n do begin
  for j:=1 to m do begin
   read(x);
   if x=1 then link(i+m,j)
  end;
  readln
 end;
 for i:=1 to m do d[u[i]]:=i;
 for i:=m+1 to m+n do r[l[i]]:=i;
 flag:=false;
 dfs(0);
 if flag then writeln('Yes, I found it')
         else writeln('It is impossible')
end;
begin
 while not(seekeof) do init;
end.


c++版

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <cassert>
using namespace std;
int g[100][500];
int l[200000],r[200000],u[200000],d[200000],R[200000],C[200000];
int row[200000],clo[200000],v[200000];
int n,m,ss;
int ori()
{
    ++ss;
    l[ss]=r[ss]=u[ss]=d[ss]=ss,R[ss]=C[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]);
}
void build()
{
    ss=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
,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++)
        for (int j=1;j<=m;j++) 
            if (g[i][j]) add(i,j);
}
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]);
		}
	}
}
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]);
		}
	}
}
bool DLX(int s,int step)
{
	if (r[s]==s) return 1;
	int x;
	x=r[s],del(x);
	for (int i=x;d[i]!=x;) {
		i=d[i];
//		cout<<'!'<<i<<endl;
		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() {
    for (;scanf("%d%d",&n,&m)==2;) {
//		cout<<n<<' '<<m<<endl;
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
                scanf("%d",&g[i][j]);
        build();
        if (DLX(clo[0],0)) {
            printf("Yes, I found it\n");
        }
        else {
            printf("It is impossible\n");
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: