PAT_1072. Gas Station(Dijkstra最短路)

#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int maxint=99999;
struct yuandian
{
	int stationId;
	double cloestDist,averageDist;
}Hxd[15];
int N,M,K,D,hxdIndex=0;
int G[1024][1024];	//矩阵表示图
bool s[1024];		//S集合
double dist[1024];	//dist数组(当前状态下源点到其他所有点的最短路径)
int cmp(yuandian a,yuandian b)
{
	if(a.cloestDist==b.cloestDist)
	{
		if(a.averageDist==b.averageDist)
			return a.stationId<b.stationId;
		else
			return a.averageDist<b.averageDist;
	}
	else
		return a.cloestDist>b.cloestDist;
}
void Dijkstra(int v)
{
	//初始化
	for(int i=1;i<=N+M;i++)
	{
		dist[i]=G[v][i];
		s[i]=false;
	}
	//将源点放入S集合
	s[v]=true;
	dist[v]=0;
	//将剩下的点放入S集合
	for(int i=2;i<=N+M;i++)
	{
		//找到一个点放入集合S
		int u;
		double mindist=maxint;
		for(int j=1;j<=N+M;j++)
		{
			if(s[j]==false&&dist[j]<mindist)
			{
				mindist=dist[j];
				u=j;
			}
		}
		s[u]=true;
		//更新dist数组
		for(int j=1;j<=N+M;j++)
			if(s[j]==false&&G[u][j]!=maxint&&dist[u]+G[u][j]<dist[j])
				dist[j]=dist[u]+G[u][j];
	}


	//本题逻辑
	Hxd[hxdIndex].cloestDist=dist[1];
	double sum=0;
	for(int i=1;i<=N;i++)
	{
		sum+=dist[i];
		if(dist[i]>D)
			return;
		if(dist[i]<Hxd[hxdIndex].cloestDist)
			Hxd[hxdIndex].cloestDist=dist[i];	
	}
	Hxd[hxdIndex].averageDist=sum/N;
	Hxd[hxdIndex].stationId=v;
	hxdIndex++;
}

int main()
{
	for(int i=1;i<1024;i++)
		for(int j=1;j<1024;j++)
			if(i==j)
				G[i][j]=0;
			else
				G[i][j]=maxint;

	scanf("%d%d%d%d",&N,&M,&K,&D);
	string a,b,c;
	for(int i=1;i<=K;i++)
	{
		cin>>a>>b>>c;
		int num1,num2;
		if(a[0]=='G')
			num1=N+atoi(a.substr(1).c_str());
		else
			num1=atoi(a.c_str());
		if(b[0]=='G')
			num2=N+atoi(b.substr(1).c_str());
		else
			num2=atoi(b.c_str());
		G[num1][num2]=G[num2][num1]=atoi(c.c_str());
	}

	//Dijkstra算法
	for(int i=N+1;i<=N+M;i++)
		Dijkstra(i);
	
	sort(Hxd,Hxd+hxdIndex,cmp);
	if(hxdIndex!=0)
		printf("G%d\n%.1lf %.1lf",Hxd[0].stationId-N,Hxd[0].cloestDist,Hxd[0].averageDist);
	else
		printf("No Solution");
	return 0;
}

 


这题显然是要求解图的某个点到图的所有其他点的最短距离,因此不难想到Dijkstra算法,题目的细节挺多,要仔细地做。

在输入的处理上,我用string接受输入,判断是否是候选点(候选点均为G开头),把形如G1,G2...GM的候选点转换成数字(这与house的数量有关,

如G1=house的总数量+1,以此类推),建图之后从第一个候选点开始调用Dijkstra算法,每次运算完毕都会得到一个dist数组,表示了从这个候选点

到其他所有house的最短距离,再按照题意完成相应的处理,保存在结构体数组中。

最后对这个结构体数组进行排序,优先级如下:

1.距离当前候选点最近的house的距离 大者优先

2.当前候选点与house的平均距离 小者优先

3.当前候选点的编号 小者优先


做这题之前没有认认真真地学一遍Dijkstra算法,现在总算是掌握了。

回忆一次Dijkstra算法的思路:


Dijkstra算法主要维护一个S集合和一个U集合,S集合表示已经求出最短路径的点,U集合表示还未求出最短路径的点,Dijkstra的过程就是将U集合中的点慢慢

地加入到S集合中,在这个过程中源点到所有其他点的距离就被求出来了,如何从U集合中选择恰当的点是Dijkstra算法的关键,挑选的依据是dist[]数组,这个

数组表示当前状态下源点到其他点的最短路径,每次选择就选U集合中的与源点的最短路径最小的那个点,加入S集合后,刚加入的点与源点的最短距离就已经

定下了,那么以这个点为中间点,再次更新dist数组,得到新的最短路径,如此反复,便可求出所有点到源点的最短路径。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值