PAT甲级1072 Gas Station (30分)|C++实现

一、题目描述

原题链接
A gas station has to be built at such a location that the minimum distance between the station and any of the residential housing is as far away as possible. However it must guarantee that all the houses are in its service range.

Now given the map of the city and several candidate locations for the gas station, you are supposed to give the best recommendation. If there are more than one solution, output the one with the smallest average distance to all the houses. If such a solution is still not unique, output the one with the smallest index number.

Input Specification:

在这里插入图片描述

​​Output Specification:

在这里插入图片描述

Sample Input 1:

4 3 11 5
1 2 2
1 4 2
1 G1 4
1 G2 3
2 3 2
2 G2 1
3 4 2
3 G3 2
4 G1 3
G2 G1 1
G3 G2 2

Sample Output 1:

G1
2.0 3.3

Sample Input 2:

2 1 2 10
1 G1 9
2 G1 20

Sample Output 2:

No Solution

二、解题思路

Dijkstra算法的变体。给出房子和加油站的候选地址以及若干条路线,要求我们找出能使加油站到住宅区的最短距离最大的地址。要找最短距离,肯定要用到Dijkstra算法,但是由于有多个加油站,所以我们在外面要加一层循环,以各个加油站为起点。这道题有一个很巧妙的地方,就是把住宅区的房子编号设为1到N,加油站选址设为N+1到N+M。具体细节请看代码注释。

三、AC代码

#include<iostream>
#include<cstdio>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
const int maxn = 1020;
const int INF = 100000000;
int G[maxn][maxn], dis[maxn];   //邻接矩阵,到各点的最短距离
bool vis[maxn]; //标记是否已经访问过
int N, M, K;    //房子总数,加油站可选位置总数,输入路线的数目
double D;   //服务范围
int main()
{
    
    
    scanf("%d%d%d%lf", &N, &M, &K, &D);
    fill(dis, dis+maxn, INF);
    fill(G[0], G[0]+maxn*maxn, INF);
    for(int i=0; i<maxn; i++)   G[i][i] = 0;
    string tmp1, tmp2;
    int tmp, temp1, temp2;
    for(int i=0; i<K; i++)  //输入
    {
    
    
        cin >> tmp1 >> tmp2;
        scanf("%d", &tmp);
        if(tmp1[0] == 'G')
        {
    
    
            tmp1 = tmp1.substr(1);
            temp1 = N + stoi(tmp1);
        }
        else    temp1 = stoi(tmp1);
        if(tmp2[0] == 'G')
        {
    
    
            tmp2 = tmp2.substr(1);
            temp2 = N + stoi(tmp2);
        }
        else    temp2 = stoi(tmp2);
        G[temp1][temp2] = G[temp2][temp1] = min(tmp, G[temp1][temp2]);
    }
    int ansid = -1;
    double ansdis = -1, ansavg = INF;
    for(int index = N+1; index <= N+M; index++) //遍历加油站的位置
    {
    
    
        double mindis = INF, avg = 0;   //开始Dijkstra算法
        fill(dis, dis+maxn, INF);
        fill(vis, vis+maxn, false);
        dis[index] = 0;
        for(int i=0; i<N+M; i++)    //更新到各点的最小距离
        {
    
    
            int u=-1, minn = INF;
            for(int j=1; j<=N+M; j++)
            {
    
    
                if(!vis[j] && dis[j] < minn)
                {
    
    
                    u = j;
                    minn = dis[j];
                }
            }
            if(u == -1) break;
            vis[u] = true;
            for(int v=1; v<=N+M; v++)
            {
    
    
                if(!vis[v] && dis[v] > dis[u] + G[u][v])    dis[v] = dis[u] + G[u][v];
            }
        }
        for(int i=1; i<=N; i++) //遍历所有住宅区的房子
        {
    
    
            if(dis[i] > D)  //不在服务范围内,舍掉这个加油站
            {
    
    
                mindis = -1;
                break;
            }
            if(dis[i] < mindis) mindis = dis[i];    //计算该加油站到住宅区的最小距离
            avg += 1.0*dis[i];
        }
        if(mindis == -1)    continue;
        avg /= N;
        if(mindis > ansdis) //优先选择最小距离最大的加油站
        {
    
    
            ansid = index;
            ansdis = mindis;
            ansavg = avg;
        }
        else if(mindis == ansdis && avg < ansavg)   //如果距离相同,选平均距离最小的
        {
    
    
            ansid = index;
            ansavg = avg;
        }
    }
    if(ansid == -1) printf("No Solution");
    else printf("G%d\n%.1f %.1f", ansid-N, ansdis, ansavg);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42393947/article/details/108723134