PAT甲级-1072 Gas Station

题目

题目大意

给出房屋数目n,候选加油站的个数m,路的数目k,最大服务范围k。要求从m个站点中选出最佳站点,使得该站点到居民房屋的最短距离尽可能大,但是也不能超过最大服务范围,否则无法提供服务。如果有多个满足条件的节点,按照 最短距离 > 到各个房屋的平均距离 > 站点id 的优先级,输出第一个站点,即为最佳站点。还要输出该站点到房屋的最短距离和平均距离。如果res中没有元素,输出“No Solution”。

思路

房屋的标号从1到n,而候选加油站的标号是从G1到Gm,可以将加油站节点放在房屋节点的后面,建立一个map映射,从名字G1映射到标号n + 1,从而将加油站也加入图中。为了后续构建图方便,将房屋也加入map中,即1对应1。

选出最佳站点,自然是要遍历每个站点,对每个站点都要进行迪杰斯特拉得到dist数组。然后根据题意筛选合适的站点,再根据题目优先级排序,输出第一个站点相关值即可。为了输出方便,用res结构体数组存储满足条件的站点,再sort排序。

知识点

保留一位小数可以用<cmath>中的round()函数,先乘以10,四舍五入为整数后,再除以10。

代码

#include <iostream>
#include <vector>
#include <climits>
#include <map>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;

int n, m, k, d, num;
int g[1015][1015] = {0};
map<string, int> mp;  // 各节点的名字索引对照
vector<int> dist;

struct sta{
    string id;
    double minDis;  // 到各房屋的最小距离
    double avgDis;  // 到各房屋的平均距离
};
vector<sta> res;

void dijie(int start){
    dist[start] = 0;
    bool visited[1015] = {false};
    for (int cnt = 0; cnt < num; cnt++){
        int now = -1, minl = INT_MAX;
        for (int i = 1; i <= num; i++){
            if (!visited[i] && dist[i] < minl){
                minl = dist[i];
                now = i;
            }
        }  // 找到要激活的节点

        if (now == -1){
            return;
        }
        visited[now] = true;

        for (int i = 1; i <= num; i++){
            if (!visited[i] && g[now][i] < INT_MAX){
                dist[i] = min(dist[i], dist[now] + g[now][i]);
            }
        }  // 更新最短路径
    }
}

bool cmp(sta x, sta y){
    if (x.minDis != y.minDis)
        return x.minDis > y.minDis;  // 先比较最小距离
    if (x.avgDis != y.avgDis)
        return x.avgDis < y.avgDis;  // 再比较平均距离
    return x.id < y.id;  // 最后按 ID 排序
}

int main(){
    cin >> n >> m >> k >> d;
    num = n + m;
    for (int i = 1; i <= n; i++){
        string s = to_string(i);  // 用to_string()将数字转换为字符串
        mp[s] = i;
    }
    for (int i = 1; i <= m; i++){
        string s = "G" + to_string(i);
        mp[s] = n + i;
    }  // 构造map
    for (int i = 1; i <= num; i++){
        for (int j = 1; j <= num; j++){
            g[i][j] = (i == j) ? 0 : INT_MAX;
        }
    }  // 初始化图
    for (int i = 0; i < k; i++){
        string p1, p2;
        int dis;
        cin >> p1 >> p2 >> dis;
        g[mp[p1]][mp[p2]] = g[mp[p2]][mp[p1]] = dis;
    }  // 构造图

    dist.resize(num + 1);
    for (int i = n + 1; i <= num; i++){
        fill(dist.begin(), dist.end(), INT_MAX);  // 重置dist数组
        dijie(i);
        int sum = 0, maxl = 0, minl = INT_MAX;
        for (int j = 1; j <= n; j++){
            sum += dist[j];
            maxl = max(maxl, dist[j]);
            minl = min(minl, dist[j]);
        }  // 距离该站点最远房屋的距离和最近房屋的距离
        if (maxl <= d){
            string name = "G" + to_string(i - n);
            sta node = {name, minl, sum * 1.0 / n};
            res.push_back(node);
        }  // 满足条件的站点加入res数组
    }

    if ((int)res.size()){
        sort(res.begin(), res.end(), cmp);
        cout << res[0].id << endl;
        res[0].avgDis = round(res[0].avgDis * 10) / 10.0;  // 先乘以10,用round()四舍五入到整数,再除以10
        printf("%.1lf %.1lf", res[0].minDis, res[0].avgDis);
    }else{
        cout << "No Solution";
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_74092648/article/details/143168801