A*k最短路讲解

A*k最短路讲解

在讲解之前你可能需要了解一下 dijstra的堆实现
Dijstra求k短路
在松弛的过程中如果把每个点都加进优先队列(堆),那么如果有泛化的点p在第t次出队,那么此时就能得到源点到p点的第t短的路。但是这个方法用来求k短路过于慢,所以就有了A*来加速寻找k短路的过程。
A*
A*本质上就是使用了优先队列的bfs。但是优先队列的优先性由一个确定值与一个估值的和来确定。
在这里我们假定某个点的确定值为g,估值为h,且该点终点的实际距离为h1,那么搜索的过程中,g代表起点到该点的实际距离,h代表该点到终点的估算距离(这个值可由算法设计者自由算出),h1代表该点到终点的实际距离。
那么我们能得出以下结论:
   1.当h < h1时,搜索范围较广但结果准确
   2.当h == h1时,搜索范围较小但结果准确
   1.当h > h1时,搜索范围最小但结果不准确
A* 求最短路
poj2449模板题,代码如下
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<queue>
#define ll long long 
#define mmset(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N = 1e3 +500,M = 1e5+500;
struct node
{
	int to,w,next;
	node()
	{
		
	};
	node(int _to, int _w, int _next)
	{
		to = _to;
		w = _w;
		next = _next;
	};
};
struct point
{
	int p, g, h;
	point()
	{
		
	};
	point(int _p, int _g, int _h)
	{
		p = _p;
		g = _g;
		h = _h;
	};
	bool operator < (point two) const
	{
		return g + h > two.g + two.h;
	}
};
int head[N],dis[N], head2[N];
node edges[M], edges2[M];
int len1,len2;
void addEdge(int a, int b, int c)
{
	edges[len1] = node(b,c,head[a]);
	head[a] = len1++;
	edges2[len2] = node(a,c,head2[b]);
	head2[b] =  len2++;
};
void dijstra(int s)
{
	mmset(dis,0x3f);
	dis[s] = 0;
	priority_queue <point> que;
	que.push(point(s,0,0));
	while(!que.empty())
	{
		point now = que.top();
		que.pop();
		for(int i = head2[now.p]; i != -1; i = edges2[i].next)if(dis[edges2[i].to] > dis[now.p] +  edges2[i].w)
		{
			dis[edges2[i].to] = dis[now.p] +  edges2[i].w;
			que.push(point(edges2[i].to,dis[edges2[i].to],0));
		}
	}
}
int Astart(int s, int e, int k)
{	
    if(dis[s] == 0x3f3f3f3f)
    return -1;
	priority_queue <point> que;
	que.push(point(s,0,0));
	int t = 1;
	while(!que.empty())
	{
		point now = que.top();
		que.pop();
		if(now.p == e)
		{
			if(t == k)
			{
				return now.g; 
			}
			t++;
		}
		for(int i = head[now.p]; i != -1; i = edges[i].next)
		{
			que.push(point(edges[i].to, now.g + edges[i].w, dis[edges[i].to]));
		}
	}
	return -1;
	
}
/*
2 2
1 2 5
2 1 4
1 2 2
*/
int main()
{
	int n,m;
	int a,b,c;
	len1 = len2 = 1;
	mmset(head,-1);
	mmset(head2,-1);
	scanf("%d %d",&n,&m);
	for(int i = 1; i <= m;i++)
	{
		scanf("%d %d %d",&a,&b,&c);
		addEdge(a,b,c);
	}
	int s,e,k;
	scanf("%d %d %d",&s,&e,&k);
	dijstra(e);
	if(s == e)
	{
		k++;
	}
	int res = Astart(s,e,k);
	printf("%d\n",res);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值