POJ 2449 Remmarguts' Date ——A*算法求k短路

启发式搜索题目,裸的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.



 

你可能感兴趣的:(Date)