PTA 垃圾箱分布

 吐槽一下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;
}

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值