呕。。这一题卡了两天才过。。。原来要用到双向宽搜,即从目标状态向前,初始状态向后进行宽搜,出现相同状态即完成搜索。。。这样时间和空间相对单向宽搜都能得到很大的优化。
附代码:
program P1099;
var
StoreA,StoreB:array[1..100000] of string;
Way:array[1..6,1..2] of string;
n,left,right,head,tail:longint;
Aim:string;
procedure ScreenInput;//刚开始写了一种比较麻烦的变换方法
var //后来删掉重写,读入就保留了,这种读入有点繁琐。
c:char;
i,Way_Num:longint;
s:string;
begin
n:=0;
read(c);
for i:=1 to 6 do
begin
Way[i,1]:='';
Way[i,2]:='';
end;
StoreA[1]:='';
Aim:='';
while c<>' ' do
begin
StoreA[1]:=StoreA[1]+c;
read(c);
end;
while not(eoln) do
begin
read(c);
Aim:=Aim+c;
end;
readln;
Way_Num:=0;
readln(s);
while s<>'' do
begin
inc(Way_Num);
i:=1;
while s[i]<>' ' do
begin
Way[Way_Num,1]:=Way[Way_Num,1]+s[i];
inc(i);
end;
inc(i);
while i<=length(s) do
begin
Way[Way_Num,2]:=Way[Way_Num,2]+s[i];
inc(i);
end;
readln(s);
end;
StoreB[1]:=Aim;
n:=Way_Num;
left:=1;
right:=1;
head:=1;
tail:=1;//正向和反向搜索的头和尾
end;
function UnChongfuA(a:string):boolean;//正向搜索的判重
var
i:longint;
begin
for i:=1 to right do
if a=StoreA[i] then exit(false);
exit(true);
end;
function UnChongfuB(a:string):boolean;//反向搜索的判重
var
i:longint;
begin
for i:=1 to tail do
if a=StoreB[i] then exit(false);
exit(true);
end;
procedure work(k:longint);
var
num,now,len,choose,kk:longint;
i,j:byte;
a,b:string;
flag:boolean;
begin
if k>5 then
begin
writeln('NO ANSWER!');
halt;
end;//正向和反向搜索都超过了五步,即意味十步之内无法完成变换
now:=right;
for num:=left to right do
begin
len:=length(StoreA[num]);
a:=StoreA[num];
for i:=n downto 1 do
begin
j:=pos(Way[i,1],a);
if pos(Way[i,1],a)<>0 then
while j<=len-length(Way[i,1])+1 do
begin
if copy(a,j,length(Way[i,1]))=Way[i,1] then flag:=true else flag:=false;
if flag then
begin
b:=copy(a,1,j-1)+Way[i,2]+copy(a,j+length(Way[i,1]),length(a)-j-length(Way[i,1])+1);
if UnChongfuA(b) then
begin
inc(now);
StoreA[now]:=b;
end;
for kk:=head to tail do
if StoreB[kk]=StoreA[now] then
begin
writeln(k+k-1);
halt;
end;
j:=j+length(Way[i,1])-1;
end;
inc(j);
end;
end;
end;//正向搜索
left:=right+1;
right:=now;
now:=tail;
for num:=head to tail do
begin
len:=length(StoreB[num]);
a:=StoreB[num];
for i:=n downto 1 do
begin
j:=pos(Way[i,2],a);
if pos(Way[i,2],a)<>0 then
while j<=len-length(Way[i,2])+1 do
begin
if copy(a,j,length(Way[i,2]))=Way[i,2] then flag:=true else flag:=false;
if flag then
begin
b:=copy(a,1,j-1)+Way[i,1]+copy(a,j+length(Way[i,2]),length(a)-j-length(Way[i,2])+1);
if UnChongfuB(b) then
begin
inc(now);
StoreB[now]:=b;
end;
for kk:=left to right do
if StoreA[kk]=StoreB[now] then
begin
writeln(k+k);
halt;
end;
j:=j+length(Way[i,2])-1;
end;
inc(j);
end;
end;
end;//反向搜索
head:=tail+1;
tail:=now;
work(k+1);
end;
begin
ScreenInput;
work(1);
end.