[SDOI2010]魔法猪学院

K短路,A*

新鲜出炉的A*
A是什么,其实就是bfs,只不过加了一个估价函数h(x),并把队列换成了优先队列。令h(x)==已经花费的代价,f(x)=g(x)+h(x),,那么f(x)就是优先队列的比较标准。这样我们就会尽可能向最优解的方向搜索,我们如果想要求最优解,就跑A,每次扩展状态,压入队列中,如果感觉要T了,直接结束程序,那么解极为可能就是最优解。

K短路有一个性质:估价函数是100%正确的,我们就利用优先队列扩展状态,如果我们到达了终点,就cnt++一次,直到cnt==k为止。这样我们就不会重复搜索。
但是,这种算法空间复杂度极高,IDA*正在学。

code:(92分)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<cstring>
#include<vector>
#include<stack>
#define db double
using namespace std;
const int maxn=400006;
int head[maxn],cur,fhead[maxn];
struct hzw
{
	int to,next;
	db v;
}e[maxn],ed[maxn];
inline void add(int a,int b,db c,hzw e[],int head[])
{
	e[cur].to=b;
	e[cur].next=head[a];
	e[cur].v=c;
	head[a]=cur++;
}
typedef pair <double,int>p;
int n,m;
double dis[maxn];
double k;
inline void dij(int firs)
{
	for (int i=1;i<=n;++i) dis[i]=1e17;
	priority_queue<p,vector<p>,greater<p> >q;
	q.push(p(0,firs));
	dis[firs]=0;
	while (!q.empty())
	{
		p fr=q.top();
		q.pop();
		int s=fr.second;
		if (dis[s]<fr.first) continue;
		for (int i=fhead[s];i!=-1;i=ed[i].next)
		{
			int v=ed[i].to;
			double w=ed[i].v;
			if (dis[v]>dis[s]+w)
			{
				dis[v]=dis[s]+w;
				q.push(p(dis[v],v));
			}
		}
	}
}
struct gk
{
	db l,rnd;
	int id;
	bool operator <(const gk &rhs) const
	{
		return l+rnd>rhs.l+rhs.rnd;
	}
};
inline int A_star(double lmt)
{
	priority_queue<gk>q;
	int cnt=0;
	q.push((gk){0,dis[1],1});
	while (!q.empty())
	{
		gk all=q.top();
		q.pop();
		int s=all.id;
		db leth=all.l,fina=all.rnd;
		if (s==n)
		{
			lmt-=leth;
			if (lmt<=0) return cnt;
			cnt++;
			continue;
		}
		for (int i=head[s];i!=-1;i=e[i].next)
		{
			int v=e[i].to;
			double w=e[i].v;
			q.push((gk){leth+w,dis[v],v}); 
		} 
	}
	return cnt;
}
signed main()
{
	memset(head,-1,sizeof(head));
	memset(fhead,-1,sizeof(fhead));
	cin>>n>>m>>k;
	for (int i=1,a,b;i<=m;++i)
	{
		db c;
		scanf("%d%d%lf",&a,&b,&c);
		add(a,b,c,e,head);
		add(b,a,c,ed,fhead);
	}
	dij(n);
	cout<<A_star(k);
	return 0;
}

总结:

A*算法适合解决寻找路径问题,她能尽可能的像最优解逼近。

posted @ 2018-09-22 11:41  Splitor  阅读(120)  评论(0编辑  收藏  举报