其实就是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.
{ 跳马问题,从一个点到另一个点的最少步数 双向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.