吐槽一下PTA里面的“GM”实际上是“G10”...
题目
大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁都不愿意守着垃圾箱住。所以垃圾箱的位置必须选在到所有居民点的最短距离最长的地方,同时还要保证每个居民点都在距离它一个不太远的范围内。
现给定一个居民区的地图,以及若干垃圾箱的候选地点,请你推荐最合适的地点。如果解不唯一,则输出到所有居民点的平均距离最短的那个解。如果这样的解还是不唯一,则输出编号最小的地点。
代码
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <queue>
#include <string>
#include <vector>
#define INF 0x3f3f3f3f
using namespace std;
int n, m;
struct node {
int index;
double min_dist;
double max_dist;
double average_dist;
node() : index{0}, min_dist{0}, max_dist{0}, average_dist{0} {};
node(int _index, double _min_dist, double _max_dist, double _average_dist)
: index{_index},
min_dist{_min_dist},
max_dist{_max_dist},
average_dist{_average_dist} {}
};
inline int get_indices(const string& str) {
if (str[0] == 'G') {
if (str.size() == 3) {
return n + 10;
} else {
return n + (str[1] - '0');
}
} else
return stoi(str);
}
inline string get_name(const int& index) {
if (index == 10) {
return "G10";
} else {
string res = "G";
res += index + '0';
return res;
}
}
inline double r(double x) { return round(x * 10) / 10; }
typedef pair<int, int> P;
vector<int> dij(const vector<vector<int>>& G, int source) {
vector<int> d(n + m, INF);
d[source] = 0;
priority_queue<P, vector<P>, greater<P>> que; // cost destination
que.push({0, source});
while (!que.empty()) {
P p = que.top();
que.pop();
int cost = p.first;
int v = p.second; // 离源最近的点,用该点松弛
if (d[v] < cost) {
continue;
}
for (int i = 0; i < n + m; ++i) {
if (d[i] > d[v] + G[v][i]) {
d[i] = d[v] + G[v][i];
que.push({d[i], i});
}
}
}
return d;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int k, max_distance;
cin >> n >> m >> k >> max_distance;
vector<vector<int>> G(n + m, vector<int>(n + m, INF));
for (int i = 0; i < n + m; i++) {
G[i][i] = 0;
}
while (k--) {
string a, b;
int dist;
cin >> a >> b >> dist;
int p1 = get_indices(a) - 1;
int p2 = get_indices(b) - 1;
G[p1][p2] = dist;
G[p2][p1] = dist;
}
vector<int> bin[m];
for (int i = 0; i < m; ++i) {
bin[i] = dij(G, n + i);
}
vector<double> min_dists(m, INF);
vector<double> max_dists(m, 0);
vector<double> average_dists(m, 0);
vector<node> nodes(m);
for (int i = 0; i < m; ++i) {
double sum = 0;
for (int j = 0; j < n; ++j) {
if (min_dists[i] > bin[i][j]) {
min_dists[i] = bin[i][j];
}
if (max_dists[i] < bin[i][j]) {
max_dists[i] = bin[i][j];
}
sum += bin[i][j];
}
average_dists[i] = sum / n;
}
for (int i = 0; i < m; ++i) {
nodes[i] = node(i + 1, min_dists[i], max_dists[i], average_dists[i]);
}
const auto f = [](const node& x, const node& y) {
if (x.min_dist > y.min_dist) {
return true;
} else if (x.min_dist == y.min_dist) {
if (x.average_dist < y.average_dist) {
return true;
} else if (x.average_dist == y.average_dist) {
if (x.index < y.index) {
return true;
}
}
}
return false;
};
sort(nodes.begin(), nodes.end(), f);
bool find_ans = false;
for (const auto& a : nodes) {
if (a.max_dist <= max_distance) {
find_ans = true;
cout << get_name(a.index) << "\n"
<< fixed << setprecision(1) << r(a.min_dist) << " "
<< r(a.average_dist);
break;
}
}
if (!find_ans) {
cout << "No Solution";
}
return 0;
}