双向广度优先搜索

其实就是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.

你可能感兴趣的:(搜索)