【bzoj1975】[Sdoi2010]魔法豬學院 A*

A*算法還是比較有意思的,本來以爲就是個搜索加減枝,現在看來是有複雜度保證的

我們到一個狀態後,處理出當前狀態的估價函數,每次選擇估價函數最小的來更新

估價函數g(n)的選取,若g(n)=實際值時,是有時間複雜度保證的,並且每次得到的答案一定是當前的最優解

bfs就是一個特殊的A*算法

這裏的估價函數g(i)可以設置成爲從T點到i點的最短路,每次用優先隊列選估價最小的那個點更新


#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<queue>
#define maxn 5010
#define maxm 201000
#define inf 1e12

using namespace std;

struct yts
{
	int now;
	double g;
};

double dis[maxn];
int q[maxn];
bool vis[maxn];

bool operator<(yts x,yts y)
{
	return x.g+dis[x.now]>y.g+dis[y.now];
}

priority_queue<yts> Q;

int head[maxn],to[maxm],next[maxm];
double len[maxm],Len[maxm];
int Head[maxn],To[maxm],Next[maxm];
int n,m,num,ans,x,y,S,T,Num;
double e,z;

void addedge(int x,int y,double z)
{
	num++;to[num]=y;len[num]=z;next[num]=head[x];head[x]=num;
}

void add(int x,int y,double z)
{
	Num++;To[Num]=y;Len[Num]=z;Next[Num]=Head[x];Head[x]=Num;
}

void spfa()
{
	for (int i=S;i<=T;i++) dis[i]=inf;
	dis[T]=0;vis[T]=1;q[1]=T;
	int l=0,r=1;
	while (l!=r)
	{
		l++;if (l==maxn) l=0;
		int x=q[l];
		for (int p=Head[x];p;p=Next[p])
		  if (dis[x]+Len[p]<dis[To[p]])
		  {
		  	dis[To[p]]=dis[x]+Len[p];
		  	if (!vis[To[p]])
		  	{
		  		r++;if (r==maxn) r=0;
		  		vis[To[p]]=1;q[r]=To[p];
		  	}
		  }
		vis[x]=0;
	}
}

void Astar()
{
	Q.push((yts){S,0});
	while (!Q.empty())
	{
		yts x=Q.top();Q.pop();
		if (x.now==T)
		{
			e-=x.g;
			if (e<0) return;
			ans++;
			continue;
		}
		if (x.g+dis[x.now]>e) continue;
		for (int p=head[x.now];p;p=next[p]) Q.push((yts){to[p],x.g+len[p]});
	}
}

int main()
{
	scanf("%d%d%lf",&n,&m,&e);
	for (int i=1;i<=m;i++)
	{
		scanf("%d%d%lf",&x,&y,&z);
		addedge(x,y,z);add(y,x,z);
	}
	S=1,T=n;
	spfa();
	Astar();
	printf("%d\n",ans);
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章