启发式搜索题目,裸的A*算法。
启发式搜索中要选估价函数h,h函数必须满足h[i]<=到目标节点的实际距离,且在保证结果正确的情况下,h选得越大越好。广度优先搜索就是输在了估价函数上,它是一种特殊的启发式搜索,只不过启发函数为0罢了,所以广度优先搜索没有什么优化的余地。
根据上述要求,我选择的估价函数是这个点目标的距离。
维护一个优先队列,每次选择一个h[i]+dist[i]最小的节点进行扩展。
当目标n被访问k次时,这时候dist[n]就是答案。
代码:
Program POJ2449;//By_Thispoet Const maxn=1000; maxm=100000; Var i,j,k,m,n,p,q,s,t,o,head,tail :Longint; h :Array[1..maxn]of Int64; v :Array[1..maxn]of Boolean; pre,other,last,data,pr,ot,la :Array[1..maxm*2]of Int64; seq,sd :Array[1..maxm*50]of Int64; Procedure Down(i:Longint); var j:Longint; begin while (i<<1)<=tail do begin j:=i<<1; if (j<tail)and(sd[j+1]+h[seq[j+1]]<sd[j]+h[seq[j]]) then inc(j); if sd[i]+h[seq[i]]>sd[j]+h[seq[j]] then begin seq[i]:=seq[i] xor seq[j]; seq[j]:=seq[i] xor seq[j]; seq[i]:=seq[i] xor seq[j]; sd[i]:=sd[i] xor sd[j]; sd[j]:=sd[i] xor sd[j]; sd[i]:=sd[i] xor sd[j]; i:=j; end else break; end; end; Procedure Up(i:Longint); var j:Longint; begin while i>1 do begin j:=i>>1; if sd[i]+h[seq[i]]<sd[j]+h[seq[j]] then begin seq[i]:=seq[i] xor seq[j]; seq[j]:=seq[i] xor seq[j]; seq[i]:=seq[i] xor seq[j]; sd[i]:=sd[i] xor sd[j]; sd[j]:=sd[i] xor sd[j]; sd[i]:=sd[i] xor sd[j]; i:=j; end else break; end; end; Procedure Spfa_h(i:Longint); begin head:=0;tail:=1;seq[tail]:=i; v[i]:=true; while head<tail do begin inc(head); i:=seq[head]; j:=la[i]; while j<>0 do begin k:=ot[j]; if h[k]>h[i]+data[j] then begin if not v[k] then begin v[k]:=true; inc(tail);seq[tail]:=k; end; h[k]:=h[i]+data[j]; end; j:=pr[j]; end; v[i]:=false; end; if h[s]>(maxlongint<<2)then begin writeln(-1); halt; end; end; Procedure Spfa_d(i:Longint); begin o:=0; tail:=1;seq[1]:=i;sd[i]:=0; while (tail>0)and(tail<maxm*45)do begin i:=seq[1]; if i=t then begin inc(o); if o=p then begin writeln(sd[1]); halt; end; end; j:=last[i]; while j<>0 do begin k:=other[j]; inc(tail); seq[tail]:=k; sd[tail]:=sd[1]+data[j]; Up(tail); j:=pre[j]; end; seq[1]:=seq[1] xor seq[tail]; seq[tail]:=seq[1] xor seq[tail]; seq[1]:=seq[1] xor seq[tail]; sd[1]:=sd[1] xor sd[tail]; sd[tail]:=sd[1] xor sd[tail]; sd[1]:=sd[1] xor sd[tail]; dec(tail); if tail>0 then Down(1); end; end; BEGIN readln(n,m); for i:=1 to m do begin readln(p,q,j); inc(k); pre[k]:=last[p];last[p]:=k;other[k]:=q;data[k]:=j; pr[k]:=la[q];la[q]:=k;ot[k]:=p; end; readln(s,t,p); if s=t then inc(p); fillchar(h,sizeof(h),127); h[t]:=0; Spfa_h(t); Spfa_d(s); writeln(-1); END.