PAT - 甲级 - 1072 - Gas Station

Nothing to fear


种一棵树最好的时间是十年前,其次是现在!

那些你早出晚归付出的刻苦努力,你不想训练,当你觉的太累了但还是要咬牙坚持的时候,那就是在追逐梦想,不要在意终点有什么,要享受路途的过程,或许你不能成就梦想,但一定会有更伟大的事情随之而来。 mamba out~

2020.7.13


人一我十,人十我百,追逐青春的梦想,怀着自信的心,永不言弃!

Gas Station

考点: Dijkstra

题目大意

要建立一个汽油站,且要求汽油站距离各个住户的最短距离,尽可能地短(Dijkstra 跑不掉了),其次必须保证所有地住户都在该加油的服务范围内

给你一幅地图要求求出在哪里建立加油站最好。如果不止一个答案,输出平均距离最短地那一个,如果还是重复,输出编号最小地那一个

输出内容:1. 最佳地加油站编号。 2.该车站到达所有房子中的最短距离和平均距离

分析

需要注意的点:

  • 处理加油站的编号 令加油站从 n+1开始编号一直到n + m
  • 从[n + 1 ,n + m]逐个对以该起点进行一遍Dijkstra得到不同的答案进行比较
  • 这个题貌似不能够使用链式前向星存边,可能有很多重复得边但是权值不同,话说这样的话应该是不影响的,但是使用前向星最后一个测试点总是过不去,又找不到什么bug,若有网友有幸看到了也可以考虑一下,然后改成链接矩阵的方式,就直接AC啦。

完整代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
const int N = 2005;
int n , m , k ,ds;
int e[N][N];
int dis[N] , vis[N];
struct node{
	int id = -1, mindis = 0;
	double avg = 0x3f;
};
node res;
void Dijkstar(int s)
{
	memset(dis , 0x3f , sizeof dis);
	memset(vis , 0 , sizeof vis);
	dis[s] = 0;
	for(int k = 0;k < n + m ;k ++)
	{
		int x = -1;
		for(int i = 1;i <= n + m;i ++)
		{
			if(!vis[i] && (x == -1 || dis[i] < dis[x]))
				x = i;
		}
		vis[x] = 1;
		for(int i = 1; i <= n + m; i ++)
		{
			int y = i , w = e[x][i];
			if(vis[y])continue;
			dis[y] = min(dis[y] , dis[x] + w);
		}
	}
	double avg = 0 ;int mindis = dis[1];
	for(int i = 1;i <= n ;i ++)
	{
		if(dis[i] > ds)return;
		mindis = min(dis[i] , mindis);
		avg += 1.0 * dis[i];
	}
	avg = avg / n;
	//printf("id = %d avg = %f mindis = %.1f\n", s,avg , (double)mindis);
	if (mindis > res.mindis) {
		res.id = s;
		res.mindis = mindis;
		res.avg = avg;
	}
	else if(mindis == res.mindis && avg < res.avg) {
		res.id = s;
		res.avg = avg;
	}
}
int main()
{
	memset(e , 0x3f , sizeof e);
	for(int i = 0;i < N;i ++)e[i][i] = 0;
	cin >> n >> m >> k >> ds;
	int a , b , c;string sa , sb;
	// 从n + 1 -> n + m 为加油站的id 分别为 G1,G2....
	for(int i = 0;i < k;i ++)
	{
		cin >> sa >> sb >> c;
		if(sa[0] == 'G')a = stoi(sa.substr(1)) + n;
		else a = stoi(sa);
		if(sb[0] == 'G')b = stoi(sb.substr(1)) + n;
		else b = stoi(sb);
		e[a][b] = e[b][a] = c;
	}//对每一个加油站进行一次Dijkstra
	for(int i = n + 1;i <= n + m;i ++){
		Dijkstar(i);
	}
	if(res.id == -1)cout << "No Solution" << endl;
	else printf("G%d\n%.1f %.1f", res.id - n , (double)res.mindis ,res.avg);
	return 0;
}
posted @ 2020-07-14 09:38  _starsky  阅读(103)  评论(0编辑  收藏  举报