双向广度优先搜索

其实就是BFS,从初始状态和目标状态同时搜索,什么时候撞上了就是找到了。但是实现起来比较麻烦。我模仿了一个程序写了NOIp2002的子串变换,采用的是节点少的先扩展。然后自己写了POJ1915,但是调试不出来。于是又模仿了一个程序写了交替扩展节点的程序,发现代码能精简不少。

上百行的程序必须注意代码的质量了。否则理解和调试会很麻烦的。

下面是两个程序。

 

字串变换

{
简单的搜索题,写了一个BFS,5个点过了4个,估计也许是字符串中出现好几个子串都可以变换的情况没有考虑到。另外运行效率不高,或许要写个hash判重。

然后写了一个双向广搜,算是第一个双向广搜程序了。双向广搜一般代码很长,但这题比较简单而且我模仿的这个程序写得还可以,所以不到百行。其实也不难理解,就是实现的时候要掌握好细节。

另外我模仿的这个程序复制字符串的时候都是多复制几位的,但是能AC。貌似PASCAL比较或复制字符串的时候会自动忽略无效的字符。

2011-09-15 23:15
}


type
  node=record
    s:string;
    depth:longint
  end;
  queue=record
    data:array[1..8000] of node;
    head,tail:longint;
  end;

var
  a:array[0..10,0..1] of string;
  q:array[0..1] of queue;
  i,j,n:longint;
  s,temp:string;

function check(s:string; sign:longint):longint;
var
  i:longint;
begin
  for i:=1 to q[sign].tail do
    if q[sign].data[i].s=s then
      exit(-1);
  for i:=1 to q[1-sign].tail do
    if q[1-sign].data[i].s=s then
      exit(i);
  exit(0);
end;

procedure expand(s:longint);
var
  i,j,len,lenx,pos,judge:longint;
  x:string;
begin
  inc(q[s].head);
  x:=q[s].data[q[s].head].s;
  len:=length(x);
  for i:=1 to n do
  begin
    lenx:=length(a[i,s]);
    for j:=1 to len-lenx+1 do
      if copy(x,j,lenx)=a[i,s] then
      begin
        temp:=copy(x,1,j-1)+a[i,1-s]+copy(x,j+lenx,len);
        judge:=check(temp,s);
        if (judge<>0) and (judge<>-1) then
        begin
          writeln(q[s].data[q[s].head].depth+1+q[1-s].data[judge].depth);
          halt;
        end
        else if judge=0 then
        begin
          inc(q[s].tail);
          q[s].data[q[s].tail].s:=temp;
          q[s].data[q[s].tail].depth:=q[s].data[q[s].head].depth+1;
        end;
      end;
 end;
end;

begin
  while (not eof) and (s<>'I love sry') do
  begin
    readln(s);
    a[n,0]:=copy(s,1,pos(' ',s)-1);
    a[n,1]:=copy(s,pos(' ',s)+1,length(s));
    inc(n);
  end;
  dec(n);
  if a[0,0]=a[0,1] then
  begin
    writeln(0);
    halt;
  end;
  for i:=0 to 1 do
  begin
    q[i].head:=0;
    q[i].tail:=1;
    q[i].data[1].s:=a[0,i];
  end;
  while true do
  begin
    if (q[0].tail=0) and (q[1].tail=0) then
      break;
    if (q[0].tail<q[1].tail) then
      expand(0)
    else
      expand(1);
    if q[0].data[q[0].tail].depth+q[1].data[q[1].tail].depth>10 then
      break;
  end;
  writeln('NO ANSWER!');
end.
 
 

POJ1915

{
跳马问题,从一个点到另一个点的最少步数

双向BFS,交替扩展节点。

2011-09-16 22:16
}

const
  dx:array[1..8] of longint=(1,1,-1,-1,2,2,-2,-2);
  dy:array[1..8] of longint=(2,-2,2,-2,1,-1,1,-1);

var
  n:longint;
  q:array[0..1000000] of record  x,y:longint; end;
  flag,step:Array[0..400,0..400] of longint;
  t,i,j,k:longint;
  head,tail:longint;


function check(x,y:longint):boolean;
begin
  if (x>=0)and(y>=0)and(x<n)and(y<n) then
    exit(true)
  else
    exit(false);
end;

procedure main;
var
  sx,sy,tx,ty,x,y:longint;
  xx,yy:longint;
  i,j,k:longint;
begin
  readln(n,sx,sy,tx,ty);
  if (sx=tx) and (tx=ty) then
  begin
    writeln(0);
    exit;
  end;;
  fillchar(flag,sizeof(flag),0);
  fillchar(step,sizeof(step),0);
  flag[sx,sy]:=1;
  flag[tx,ty]:=2;
  q[1].x:=sx;
  q[1].y:=sy;
  q[2].x:=tx;
  q[2].y:=ty;
  head:=0;
  tail:=2;
  while head<tail do
  begin
    inc(head);
    x:=q[head].x;
    y:=q[head].y;
    for i:=1 to 8 do
    begin
      xx:=x+dx[i];
      yy:=y+dy[i];
      if not check(xx,yy) then continue;
      if flag[xx,yy]=0 then
      begin
        inc(tail);
        q[tail].x:=xx;
        q[tail].y:=yy;
        flag[xx,yy]:=flag[x,y];
        step[xx,yy]:=step[x,y]+1;
      end
      else if flag[xx,yy]<>flag[x,y] then
      begin
        writeln(step[xx,yy]+step[x,y]+1);
        exit;
      end;
    end;
  end;
end;


begin
  readln(t);
  for i:=1 to t do
    main;
end.

posted on 2011-09-16 22:19  oa414  阅读(1398)  评论(0编辑  收藏  举报

导航