题目
题目链接
题解
对每个垃圾箱进行一次队列优化的Dijskra,每算出一个垃圾箱到其余各个居民点的最短距离后,计算这些距离中的最大距离、最短距离。如果最大距离大于要求的距离则直接忽略这个位置放垃圾桶的情况;否则,如果最短距离小于已经记录的最大的最短距离或者最短距离等于已经记录的最大的最短距离并且距离均值小于已经记录的最小均值,则更新要输出的信息。
优先级:
- 最短距离要最大
- 距离均值要最小
- 垃圾桶编号要小(由于我们是顺序判断每种情况,所以不需要通过该条件进行更新)
注意:
直接printf("%.1lf")
输出均值是过不了样例的,但是可以AC。
通过printf进行四舍五入会存在一些问题,这也是我在输出样例的时候发现的。
printf四舍五入问题
所以最好还是通过+0.5来处理
代码
#include<bits/stdc++.h>
#define PII pair <int, int>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 5e4 + 10;
int n, m, k, MAXDIST;
int best_pos, best_mindist = INF;
int maxmindist = -1; // 最大的最短距离
int d[N];
int w[N], e[N], ne[N], h[N], idx;
double best_sum;
void add (int a, int b, int c) {
w[idx] = c, e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void Dijkstra (int x) { // Dijkstra优先队列优化模板
memset (d, 0x3f, sizeof d);
d[x] = 0;
priority_queue <PII, vector <PII>, greater<PII> > q;
q.push ({0, x});
while (q.size()) {
PII tt = q.top ();
q.pop ();
int t = tt.second;
int dist = tt.first;
if (dist != d[t]) continue;
for (int i = h[t];~i;i = ne[i]) {
int j = e[i];
if (d[j] > d[t] + w[i]) {
d[j] = d[t] + w[i];
q.push ({d[j], j});
}
}
}
}
int main()
{
memset (h, -1, sizeof h);
cin >> n >> m >> k >> MAXDIST;
while (k --) {
string a, b;
int c;
cin >> a >> b >> c;
int aa, bb;
if (a[0] == 'G') aa = atoi (a.substr(1).c_str()) + n; // 如果是垃圾箱就让编号从n+1开始
else aa = atoi (a.c_str());
if (b[0] == 'G') bb = atoi (b.substr(1).c_str()) + n;
else bb = atoi (b.c_str());
add (aa, bb, c);
add (bb, aa, c);
}
for (int i = n+1;i <= n+m;i ++) {
double sum = 0.0;
int maxdist = -1, mindist = INF;
Dijkstra (i);
// cout << "such as : ";
for (int j = 1;j <= n;j ++) {
sum += 1.0 * d[j];
maxdist = max (maxdist, d[j]); // 以第i-n号垃圾桶为起点到其他各个居民的距离的最大值
mindist = min (mindist, d[j]); // 以第i-n号垃圾桶为起点到其他各个居民的距离的最小值
// cout << d[j] << ' ';
}
// cout << endl;
// 最大距离必须小于要求 判断最小距离是否大于最大最短距离(若大于则更新)或者最小距离等于最大的最短距离,比较均值,也就是比较分子(距离和)
if (maxdist <= MAXDIST && (mindist > maxmindist || (mindist == maxmindist && sum < best_sum))) {
// 保存最佳输出答案
best_pos = i;
best_sum = sum;
best_mindist = mindist;
// 更新用于更新最佳输出答案的数据
maxmindist = mindist;
}
}
if (!best_pos) puts ("No Solution");
else printf ("G%d\n%.1lf %.1lf", best_pos-n, 1.0 * best_mindist, (int(best_sum / n * 10 + 0.5)) / 10.0);
// 这个输出真离谱,如果直接 printf("%.1lf", best_sum / n) 样例都过不了却能AC
return 0;
}
沃日,好离谱,之前写了个大根堆都尼玛能AC!