A*算法学习笔记

A*算法基本原理

A-star算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是解决许多搜索问题的有效算法。算法中的距离估算值与实际值越接近,最终搜索速度越快。

F[i]=G[i]+H[i];

这是A*算法的核心表达式,即每次取出当前代价+未来估价最小的状态其中估算值H[i]<=未来实际代价

若估算值大于未来实际代价不能保证A*算法的正确性。(此处看了<<算法竞赛进阶指南>>的反例并没有看懂,以后看懂会来补上)。

第K短路

#include<bits/stdc++.h>
using namespace std;
#define fp(i,a,b) for(register int i=a;i<=b;i++)
#define fb(i,a,b) for(register int i=a;i>=b;i--)
#define sc(a) scanf("%d",&a)
#define scf(a,b) scanf("%d%d",&a,&b)
const int MAXN=1e5+5;
struct Node{
	int f,g,h;
	bool operator<(const Node &a)const{
	    if(a.f==f) return a.g<g;
	    return a.f<f;
	}
};
struct Edge{
	int to,w,prev;
}edge1[MAXN<<1],edge2[MAXN<<1];
int n,m,s,t,k,cnt1,cnt2,ans,head1[MAXN],head2[MAXN],dis[MAXN],vis[MAXN];
inline void add(int x,int y,int w){
	edge1[++cnt1].to=y;
	edge1[cnt1].w=w;
	edge1[cnt1].prev=head1[x];
	head1[x]=cnt1;
	edge2[++cnt2].to=x;
	edge2[cnt2].w=w;
	edge2[cnt2].prev=head2[y];
	head2[y]=cnt2;
}
inline void spfa(int st){
	queue<int> q;
	memset(dis,0x3f3f3f3f,sizeof(dis));
	q.push(st);vis[st]=1;dis[st]=0;
	while(!q.empty()){
		int x=q.front();q.pop();vis[x]=0;
		for(int i=head2[x];i;i=edge2[i].prev){
			int to=edge2[i].to;
			if(dis[to]>dis[x]+edge2[i].w){
				dis[to]=dis[x]+edge2[i].w;
				if(!vis[to]){
					vis[to]=1;
					q.push(to);
				}
			}
		}
	}
}
inline int Astar(int st,int ed){
	priority_queue<Node> q;
	if(st==ed) k++;
	if(dis[st]==0x3f3f3f3f) return -1;
	struct Node t,tt;
	t.g=0;t.h=st;t.f=t.g+dis[t.h];
	q.push(t);
	while(!q.empty()){
		tt=q.top();q.pop();
		if(tt.h==ed){
			ans++;
			if(ans==k) return tt.g;
		}
		for(int i=head1[tt.h];i;i=edge1[i].prev){
			int to=edge1[i].to;
			t.g=tt.g+edge1[i].w;
			t.h=to;
			t.f=t.g+dis[to];
			q.push(t);
		}
	}
	return -1;
}
int main(){
	scf(n,m);
	fp(i,1,m){
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
	}
	scanf("%d%d%d",&s,&t,&k);
	spfa(t);
	printf("%d\n",Astar(s,t));
	return 0;
}
/*
4 5
1 2 2
2 3 3
1 3 5
2 4 1
4 3 3
1 3 3
*/

A-star算法最重要的部分就是要找到合适的估值函数。这道经典的A-star模板题的估值函数就是终点到各个点的最短路。所以需要反向建一次图,并跑一遍最短路。那么终点只需出现k次的话,那么它的当前代价即为第k短路。因为每次从优先队列里面取出来的元素都是当前条件下的最优解。这道题还需要特判一下起点与终点重合的情况。

猜你喜欢

转载自blog.csdn.net/weixin_43916777/article/details/104224307