1072 Gas Station (30 分)

1072 Gas Station (30 分)

题目大意

从m个站点中选取一个站点,让他离居民区的最近的人最远,并且没有超出服务范围。如果有很多个最远的加油站,输出距离所有居民区平均距离最小的那一个。如果平均值还是一样。输出加油站编号最小的那一个。

基本思路

这题是我做过pta上面最最最难的一道Dij题目,让我想起了高中哪会被最大值里的最小值,最小值里的最大值这类问题支配的恐惧~
因为k组边中会有重复的和两个顶点相同的情况(说明两个顶点间有多条路,应该选择最小的那条路径)(自身到自身,无效数据,应该舍弃掉),所以我们需要把G[i] [i]全部设置为0,并在读入数据时G[a][b]=G[b][a]=min(tempdis,G[a][b]),这样才能保证图本身的有效性。
根据题目意思,我们需要对m个加油站都进行一次Dij算法。对于其中某个加油站,计算出以某个加油站为起点的最近居民区。因为要在m个最近区民区中找到一个距离最大的,所以需要设置变量ansid(初始化为-1)、ansdis、ansaver记录下最终的结果。
对于每一次Dij,有以下说明:
设置居民区的编号为1~n,加油站的编号为n+1 ~ m。以当前加油站index为起点。因为加油站之间也是有连接的,所以我们需要在Dij算法中对n+m个顶点进行最短路径的计算,得到每个顶点距离当前加油站的最短距离数组d。
遍历整个数组d,如果有大于ds的元素,说明这个加油站的设置,会导致有居民区在服务区外,需要舍弃这个加油站。
遍历整个数组d,记录下最小的元素为dis并累加平均距离aver。
到这里,将得到的dis和aver与ansdis和ansaver进行比较,如果满足更优,则更新ansdis和ansaver,并把当前加油站编号index赋值给ansid。
至此,一次Dij算法结束。
当m次Dij算法结束时,如果ansid还是初始值-1,则该题无解,否则输出结果。

代码

具体数据结构和详细思路的设计请看代码:

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int INF = 100000000;
int n, m, k, ds;
int G[1020][1020];
bool visit[1020];
int d[1020];
void dijkstra(){
    for (int i = 1; i <= n + m;i++){
            int u = -1, MIN = INF;
            for (int j = 1; j <= n + m;j++){
                if(visit[j]==false&&d[j]<MIN){
                    u = j;
                    MIN = d[j];
                }
            }
            if(u==-1)
                return;
            else
                visit[u] = true;
            for (int v = 1; v <= n + m;v++){
                if((G[u][v]>0&&G[u][v]<INF)&&visit[v]==false&&d[u]+G[u][v]<d[v]){
                    d[v] = d[u] + G[u][v];
                }
            }
        }
}
int main(){
    //读入并初始化数据
    fill(G[0], G[0] + 1020 * 1020, INF);
    for (int i = 0; i < 1020;i++) G[i][i] = 0;//因为会有G1 G1 9999这样的数据,所以自身到自身的距离初始化为0
    fill(d, d + 1020, INF);
    cin >> n >> m >> k >> ds;
    for (int i = 1; i <= k; i++){
        string s1, s2;
        int temp;
        cin >> s1 >> s2 >> temp;
        int a, b;
        if(s1[0]=='G'){
            s1 = s1.substr(1);
            a = n+stoi(s1);//加油站编号位n+1~n+m
        }else{
            a = stoi(s1);//居民区编号为1~n
        }
         if(s2[0]=='G'){
            s2 = s2.substr(1);
            b = n+stoi(s2);
        }else{
            b = stoi(s2);
        }
        G[a][b] = G[b][a] = min(G[a][b], temp);//因为两个顶点之间会有多以奥路径,所以需要取最短的路径
    }
    int ansid=-1;//结果id(最终选址)
    double ansdis=-1, ansaver=INF;//结果距离,结果平均距离
    //进行m次Dij算法,以每个加油站为起点考虑问题
    for (int index = n + 1; index <= n + m;index++){
        //将dij算法需要用到的数据结构定义或者重新初始化
        double dis = INF, aver = 0; //本次Dij算法的最短距离dis,平均最短距离aver
        fill(visit, visit + 1020, false);
        fill(d, d + 1020, INF);
        d[index] = 0;
        //以index加油站为基准,进行Dij算法
        dijkstra();
        //以这个加油站位基准的情况下,查看有没有在服务区外的居民区
        int flag = 0;
        for (int i = 1; i <= n;i++){
            if(d[i]>ds){
                flag = 1;
                break;
            }
        }
        if(flag)
            continue;
        //以这个加油站位基准的情况下,寻找距离该加油站最近的居民区,更新其id、dis,并且累加aver
        for (int i = 1; i <= n;i++){
            if(d[i]<dis){
                dis = d[i];
            }
            aver +=1.0* d[i];
        }
        //上述找到了距离该加油站最近的居民区,与ansdis、ansaver进行比较
        //如果该居民区是距离基准加油站最近距离中距离最大的,更新ansid、ansdis、ansaver
        aver=aver/n;
        if(dis>ansdis){
            ansid = index;
            ansdis = dis;
            ansaver = aver;
        }else if(dis==ansdis&&aver<ansaver){
            ansid = index;
            ansaver = aver;
        }
    }
    //输出
    if (ansid == -1)
        printf("No Solution");
    else
        printf("G%d\n%.1f %.1f", ansid - n, ansdis, ansaver);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
用c++解决pipeline system consists of N transfer station, some of which are connected by pipelines. For each of M pipelines the numbers of stations A[i] and B[i], which are connected by this pipeline, and its profitability C[i] are known. A profitability of a pipeline is an amount of dollars, which will be daily yielded in taxes by transferring the gas through this pipeline. Each two stations are connected by not more than one pipeline. The system was built by Soviet engineers, who knew exactly, that the gas was transferred from Ukrainian gas fields to Siberia and not the reverse. That is why the pipelines are unidirectional, i.e. each pipeline allows gas transfer from the station number A[i] to the station number B[i] only. More over, if it is possible to transfer the gas from the station X to the station Y (perhaps, through some intermediate stations), then the reverse transfer from Y to X is impossible. It is known that the gas arrives to the starting station number S and should be dispatched to the buyers on the final station number F. The President ordered the Government to find a route (i.e. a linear sequence of stations which are connected by pipelines) to transfer the gas from the starting to the final station. A profitability of this route should be maximal. A profitability of a route is a total profitability of its pipelines. Unfortunately, the President did not consider that some pipelines ceased to exist long ago, and, as a result, the gas transfer between the starting and the final stations may appear to be impossible... Input The first line contains the integer numbers N (2 ≤ N ≤ 500) and M (0 ≤ M ≤ 124750). Each of the next M lines contains the integer numbers A[i], B[i] (1 ≤ A[i], B[i] ≤ N) and C[i] (1 ≤ C[i] ≤ 10000) for the corresponding pipeline. The last line contains the integer numbers S and F (1 ≤ S, F ≤ N; S ≠ F). Output If the desired route exists, you should output its profitability. Otherwise you should output "No solution".
最新发布
05-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值