poj2449 Remmarguts' Date A*搜索

本文探讨了A*搜索算法的核心思想及其在路径优化问题中的应用。通过反向构建边,求出每个点到终点的最短距离,然后正向搜索,最终找到第k短路径。注意避免计算节点到自身的距离。使用优先队列优化搜索过程,确保高效求解。

A*搜索主要思想:f[i] = g[i] + h[i] 。f[i] 即为所求,g[i] 表示已走过距离,h[i] 表示距离终点的距离。在优先队列中,能尽量把符合条件的方案提前,优化搜索。

对于这道题,先反向建边,求出每个点到终点的最短距离。

再正向搜索,所要记录的内容有:当前节点,已走过了距离,已走过的距离+这点到终点的距离。

每次把与这点相连的下一个点放入队列,直到第k次取出终点,便求出第k短路。

注意:自己到自己距离为0不算(坑爹)。

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
#define inf 100010
#define INF 0xffffff
struct node1
{
	int to,next,val;
};
node1 edge1[inf],edge2[inf];
int cnt1;
int head1[1010];
void add1(int f,int t,int v)
{
	edge1[cnt1].to=t;
	edge1[cnt1].val=v;
	edge1[cnt1].next=head1[f];
	head1[f]=cnt1++;
}
int cnt2;
int head2[1010];
void add2(int f,int t,int v)
{
	edge2[cnt2].to=t;
	edge2[cnt2].val=v;
	edge2[cnt2].next=head2[f];
	head2[f]=cnt2++;
}
int n,m,s,t,k;
int vis[1010],dis[1010];
void spfa()
{
	for(int i=1;i<=n;i++)
	{
		dis[i]=INF;
		vis[i]=0;
	}
	queue<int>Q;
	Q.push(t);
	dis[t]=0;
	vis[t]++;
	while(!Q.empty())
	{
		int u=Q.front();
		Q.pop();
		vis[u]--;
		if(vis[u]>n)return ;
		for(int i=head1[u];i!=-1;i=edge1[i].next)
		{
			int v=edge1[i].to;
			if(dis[v]>dis[u]+edge1[i].val)
			{
				dis[v]=dis[u]+edge1[i].val;
				if(vis[v]==0)
				{
					vis[v]++;
					Q.push(v);
				}
			}
			
		}
	}
	return ;
}
struct node
{
	int i,len,sum;
	bool operator<(const node &r ) const  //这个必须放在里面,尽管我不知道为什么。。。就因为这个,我把poj刷屏了。。。坑了爹一晚上啊!!!
    {  
        if(r.sum==sum)  
            return r.len<len;  
        return r.sum<sum;  
    }
};
int cnt;
int bfs()
{
	priority_queue<node>QQ;
	if(s==t)k++;//因为自己到自己距离为0不算
	if(dis[s]==INF)return -1;
	node st;
	st.i=s;
	st.len=0;
	st.sum=dis[s];
	QQ.push(st);
	while(!QQ.empty())
	{
		node u;
		u=QQ.top();
		QQ.pop();
		if(u.i==t)
		{
			cnt++;
		}
		if(cnt==k)
		{
			return u.len;
		}
		for(int j=head2[u.i];j!=-1;j=edge2[j].next)
		{
			node v;
			v.i=edge2[j].to;
			v.len=u.len+edge2[j].val;
			v.sum=v.len+dis[v.i];
			QQ.push(v);
		}
	}
	return -1;
}
int main()
{
	memset(head1,-1,sizeof(head1));
	memset(head2,-1,sizeof(head2));
	scanf("%d %d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int a,b,c;
		scanf("%d %d %d",&a,&b,&c);
		add1(b,a,c);
		add2(a,b,c);
	}
	scanf("%d %d %d",&s,&t,&k);
	spfa();
	printf("%d\n",bfs());
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值