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;
}