[PAT Class A shortest path C++] 1072 Gas Station (30 points)

Dijkstra

# include <iostream>
# include <algorithm>
# include <numeric>
# include <vector>
# include <set>

using namespace std;

/* 大约就是加油站要覆盖所有的居民区,然后挑选出距离加油站最近的居民楼的距离最大的加油站(大约这样污染较少) 
如果这个最大最近距离相等的话,就选择加油站到所有居民楼的平均距离更小的那个加油站
*/

const int MAXV = 1020; // 房屋和加油站的最大数
const int INF  = 0xffffff;

struct Node{
    
    int v, dis;};

int N, M, K, Ds;

vector<Node> G[MAXV];
set<int> gasStation; // AC之后觉得set并且没必要在定义容器(很多余),但是懒得改了
int dist[MAXV];
bool vis[MAXV];

// 因为非加油站的数量为N,这些编号又是从1开始,所以加上N就是加油站的编号
int getID(string S){
    
    
    return S[0] == 'G' ? N + stoi(S.substr(1)) : stoi(S);
}

void Dijkstra(int s){
    
    
    fill(dist, end(dist), INF);
    fill(vis, end(vis), false);
    dist[s] = 0;

    for(int i = 1;i <= N+M;++i){
    
     // 因为可以通过去加油站有更短句路径,所以要加上M
        int u = -1;
        int MIN = INF;
        for(int j = 1;j <= N+M;++j){
    
     // 因为可以通过去加油站有更短句路径,所以要加上M
            if(vis[j] == false && dist[j] < MIN){
    
    
                u = j;
                MIN = dist[j];                
            }
        }
        if(u == -1) return;
        vis[u] = true;
        for(Node next: G[u]){
    
    
            int v = next.v, uv_dis = next.dis;
            if(vis[v] == false){
    
    
                if(dist[u] + uv_dis < dist[v]){
    
    
                    dist[v] = dist[u] + uv_dis;
                }
            }
        }
    }
}

int main(){
    
    
    cin >> N >> M >> K >> Ds;
    for(int i = 0;i < K;++i){
    
    
        string SID1, SID2;
        int Dist;
        cin >> SID1 >> SID2 >> Dist;
        // 将 数字字符串 或 G1 等转换为int
        int ID1 = getID(SID1);
        int ID2 = getID(SID2);
        if(ID1 > N) gasStation.insert(ID1);
        if(ID2 > N) gasStation.insert(ID2);
        G[ID1].push_back({
    
    ID2, Dist});
        G[ID2].push_back({
    
    ID1, Dist});
    }

    int minStation = -1; // 最优加油站编号
    double maxDist = -1; // 最大的居民楼最近距离
    double minAvg = INF; // 最小居民楼平均距离
    for(int station: gasStation){
    
     // 枚举所有加油站的编号
        Dijkstra(station); // 获得了当前station的dist数组
        int flag = 0;
        double dis = INF, avg = 0.0;
        for(int j = 1;j <= N;++j){
    
    
            if(dist[j] > Ds){
    
     // 有居民楼超出距离
                flag = -1;
                break;
            }
            if(dist[j] < dis) dis = dist[j]; // 寻找当前station距离最近居民楼的距离
            avg += 1.0*dist[j] / N; // 计算平均数的sum
        }

        if(flag == -1) continue;
        if(dis > maxDist){
    
     // 挑选出 max(最近居民楼的距离)
            maxDist = dis;
            minAvg = avg;
            minStation = station;
        }
        else
        if(dis == maxDist){
    
    
            if(avg < minAvg){
    
    
                minAvg = avg;
                minStation = station;
            }
        }
        
    }
    if(minStation == -1) {
    
    
        cout << "No Solution\n";
    }
    else {
    
     
        cout << "G" << minStation - N << endl;
        printf("%.1f %.1f\n", maxDist, minAvg);
    }


    return 0;
}

Guess you like

Origin blog.csdn.net/MYMarcoreus/article/details/113819126