[PAT] A1072 Gas Station

最短路径

题目大意

从m个加油站里面选取1个站点,让它和离它最近的居民区距离最远,并且没有超出服务范围ds之内。如果有很多个最远的加油站,输出距离所有居民区距离平均距离最小的那个。如果平均值还是一样,就输出加油站编号最小的那个。

思路

Dijkstra算法。注意每次调用Dijkstra都要初始化。
因为加油站之间也是彼此有路连接的,所以最短路径计算的时候也要把加油站算上。因此考虑将加油站和居民点放在一起,用Dijkstra时循环的范围时1~n+m。可以根据输入的是G还是数字来判断,如果是数字就令编号为他自己,如果是G开头的,编号设为n+G后面的数字。
我是先针对每个加油站调用一次Dijkstra,将满足可连通、没有超出服务范围的所有加油站及各项参数(最近点的距离、平均距离、加油站编号)存在另一个结构体中,再统一判断求最优解。(因为数据量<=10,我就直接图方便写了个排序。最近点距离较远->平均距离较短->加油站编号较小)

坑点集中在最后一个测试点4:
(1)加油站和居民点的输入按照string,然后转成数字时要注意它不仅是1位数,可能是多位数。(str.erase(str.begin()+x);中参数是迭代器!)
(2).1f%的输出会自动四舍五入,不用+0.05。

AC代码

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
#define N 1020
#define INF 100000000
struct way {
	double dis, min;
	int index;
}ways[12];
int numways = 0;
struct node {
	int v, distance;
};
vector<node>Adj[N];
int n, m;//1~n是居民点;n+1~n+m是加油站
int dis[N];
bool vis[N] = { false };
void Dijkstra(int s) {
	int i, j;
	for (i = 0;i < N;i++) {
		dis[i] = INF;
		vis[i] = false;
	}
	dis[s] = 0;
	for (i = 0;i < n + m;i++) {
		int min = INF, u = -1;
		for (j = 1;j <= n + m;j++) {
			if (min > dis[j] && vis[j] == false) {
				min = dis[j];
				u = j;
			}
		}
		if (u == -1)return;
		vis[u] = true;
		for (j = 0;j < Adj[u].size();j++) {
			int v = Adj[u][j].v;
			if (vis[v] == false && dis[v] > dis[u] + Adj[u][j].distance) {
				dis[v] = dis[u] + Adj[u][j].distance;
			}
		}
	}
}
bool cmp(way a, way b) {
	if (a.min != b.min)return a.min > b.min;
	else if (a.dis != b.dis)return a.dis < b.dis;
	else return a.index < b.index;
}
int strtoint(string a) {
	int ans = 0;
	for (int i = 0;i < a.size();i++)
		ans = ans * 10 + a[i] - '0';
	return ans;
}
int main() {
	int i, j, k, dmax;
	scanf("%d%d%d%d", &n, &m, &k, &dmax);
	for (i = 0;i < k;i++) {
		int p1, p2, dist;
		string s_p1, s_p2;
		cin >> s_p1 >> s_p2 >> dist;		
		if (s_p1[0] == 'G') {
			s_p1.erase(s_p1.begin());
			p1 = strtoint(s_p1) + n;
		}
		else p1 = strtoint(s_p1);
		if (s_p2[0] == 'G') {
			s_p2.erase(s_p2.begin());
			p2 = strtoint(s_p2) + n;
		}
		else p2 = strtoint(s_p2);
		node temp;
		temp.distance = dist;
		temp.v = p1;Adj[p2].push_back(temp);
		temp.v = p2;Adj[p1].push_back(temp);
	}
	for (i = n + m;i > n;i--) {
		Dijkstra(i);
		for (j = 1;j <= n;j++)
			if (dis[j] > dmax)break;
		if (j == n + 1) {//符合条件的路径存在
			ways[numways].index = i - n;
			int dmin = INF;
			for (k = 1;k <= n;k++) {//计算总路径长和最小路径值
				if (dmin > dis[k])dmin = dis[k];
				ways[numways].dis += dis[k];
			}
			ways[numways].min = dmin;
			ways[numways].dis = ways[numways].dis / n;
			numways++;
		}
	}
	if (numways == 0)printf("No Solution\n");
	else {
		sort(ways, ways + numways, cmp);//顺手写了个排序,其实duck不必。找最小值就好了~
		printf("G%d\n%.1f %.1f\n", ways[0].index, ways[0].min, ways[0].dis);
	}
	return 0;
}

posted @ 2020-07-18 11:40  \0.0/  阅读(155)  评论(0编辑  收藏  举报