PAT甲题题解-1072. Gas Station (30)-dijkstra最短路

题意:从m个加油站里面选取1个站点,使得其离住宅的最近距离mindis尽可能地远,并且离所有住宅的距离都在服务范围ds之内。
如果有很多相同mindis的加油站,输出距所有住宅平均距离最小的那个。
如果平均值还是一样,就输出按照顺序排列加油站编号最小的。

分析:
加油站之间也是彼此有路连接的,所以最短路径计算的时候也要把加油站算上,是双向边,所以边的数组大小得开两倍。
加油站编号记为n+1~n+m,对这些点用dijkstra计算最短路径即可,这里顺便在dijkstra中进行了剪枝处理,不剪枝也没事。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <queue>
#define INF 0X3f3f3f3f
using namespace std;
/*
从m个加油站里面选取1个站点,使得其离住宅的最近距离mindis尽可能地远,并且离所有住宅的距离都在服务范围ds之内。
如果有很多相同mindis的加油站,输出距所有住宅平均距离最小的那个。
如果平均值还是一样,就输出按照顺序排列加油站编号最小的。
分析:
加油站之间也是彼此有路连接的,所以最短路径计算的时候也要把加油站算上,是双向边,所以边的数组大小得开两倍。
加油站编号记为n+1~n+m,对这些点用dijkstra计算最短路径即可,这里顺便在dijkstra中进行了剪枝处理,不剪枝也没事。
*/
const int maxn=1000+15;
int dis[maxn];
int vis[maxn];
int head[maxn];
int tot=0;
int mindis;
struct Node{
    int u;
    int dis;
    bool operator<(const Node tmp)const{
        return dis>tmp.dis;
    }
};

struct Edge{
    int to;
    int next;
    int dist;
}edge[10005*2];

void add(int u,int v,int dist){
    edge[tot].to=v;
    edge[tot].dist=dist;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void init(){
    memset(head,-1,sizeof(head));
    tot=0;
}
bool dijkstra(int s,int n){
    for(int i=0;i<maxn;i++){
        dis[i]=INF;
        vis[i]=0;
    }
    priority_queue<Node>q;
    Node st,t;
    st.u=s;
    st.dis=0;
    dis[s]=0;
    q.push(st);
    bool first=true;
    while(!q.empty()){
        st=q.top();
        q.pop();
        vis[st.u]=1;
        if(first && 1<=st.u && st.u<=n){
            if(dis[st.u]<mindis){
                return false; //剪枝,即离车站最小的距离比目前的mindis还要小,直接返回即可
            }
            first=false;
        }
        for(int k=head[st.u];k!=-1;k=edge[k].next){
            int v=edge[k].to;
            if(!vis[v] && dis[st.u]+edge[k].dist<dis[v]){
                dis[v]=dis[st.u]+edge[k].dist;
                t.u=v;
                t.dis=dis[v];
                q.push(t);
            }
        }
    }
    return true;
}
int main()
{
    int n,m,k,ds;
    char str1[10],str2[10];
    int u,v,dist;
    scanf("%d %d %d %d",&n,&m,&k,&ds);
    init();
    for(int i=0;i<k;i++){
        scanf("%s %s %d",str1,str2,&dist);
        if(str1[0]==‘G‘)
            u=atoi(str1+1)+n;
        else
            u=atoi(str1);
        if(str2[0]==‘G‘)
            v=atoi(str2+1)+n;
        else
            v=atoi(str2);
        add(u,v,dist);
        add(v,u,dist);
    }
    mindis=0;
    double avgdis=INF;
    int gasid=0;
    bool noAns=true;
    for(int i=1;i<=m;i++){
        //如果最小距离小于目前的mindis,直接跳过
        if(!dijkstra(n+i,n)){
            continue;
        }
        dist=INF;
        int sum=0;
        bool flag=true;
        for(int j=1;j<=n;j++){
            //有超出服务范围的
            if(dis[j]>ds){
                flag=false;
                break;
            }
            dist=min(dist,dis[j]);
            sum+=dis[j];
        }
        if(!flag)
            continue;
        else
            noAns=false;
        double avg=sum*1.0/n;
        if(dist>mindis){
            gasid=i;
            mindis=dist;
            avgdis=avg;
        }
        else if(dist==mindis){
            if(avg<avgdis){
                gasid=i;
                avgdis=avg;
            }
        }
    }
    if(noAns)
        printf("No Solution\n");
    else
        printf("G%d\n%.1lf %.1lf\n",gasid,(double)mindis,avgdis);
    return 0;
}

时间: 2024-10-02 07:23:37

PAT甲题题解-1072. Gas Station (30)-dijkstra最短路的相关文章

PAT甲题题解-1103. Integer Factorization (30)-(dfs)

该题还不错~. 题意:给定N.K.P,使得可以分解成N = n1^P + - nk^P的形式,如果可以,输出sum(ni)最大的划分,如果sum一样,输出序列较大的那个.否则输出Impossible. dfs枚举,为了防止超时,这里要预先将从1开始的i^p的值存储在factor数组中,直到i^p>n.然后dfs深度优先搜索,相当于把问题一步步分解,即若第一个因子是n1,则接下来我们要判断N-n1^p.k-1是否可行.同时存储当前因子的总和sum,要取sum最大的:还有上一次相加的因子的索引las

PAT甲题题解-1091. Acute Stroke (30)-BFS

题意:给定三维数组,0表示正常,1表示有肿瘤块,肿瘤块的区域>=t才算是肿瘤,求所有肿瘤块的体积和 这道题一开始就想到了dfs或者bfs,但当时看数据量挺大的,以为会导致栈溢出,所以并没有立刻写,想有没有别的办法.然而结果是,实在想不出别的办法了,所以还是尝试写写dfs.bfs. 一开始先用了dfs,最后两个样例段错误,估计是栈溢出了.之所以dfs栈溢出,因为dfs的时候每个状态都会存储在堆栈里,就好比dfs的第一个状态,一直保存到最后整个dfs结束.而bfs是存储在队列中,每次队列都会有状态取

PAT甲题题解-1111. Online Map (30)-PAT甲级真题(模板题,两次Dijkstra,同时记下最短路径)

题意:给了图,以及s和t,让你求s到t花费的最短路程.最短时间,以及输出对应的路径.   对于最短路程,如果路程一样,输出时间最少的. 对于最短时间,如果时间一样,输出节点数最少的.   如果最短路程和最短时间路径一样,合并输出一次即可. 纯粹就是练习dijkstra,没什么难的. 第一次dijkstra求最短路程,记录下每个节点的路程和时间. 第二次dijkstra求最短时间,记录下每个节点的时间和经过的节点数. pre数组用来存储前驱节点,保存路径 #include <iostream>

PAT甲题题解-1022. Digital Library (30)-map映射+vector

博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6789235.html特别不喜欢那些随便转载别人的原创文章又不给出链接的所以不准偷偷复制博主的博客噢~~ 题意:给出n本书的id.名称.作者.多个关键词.出版社.出版年然后给出m个查询,每个查询包含查询的种类.对应的内容针对每个查询,让你输出所有符合的书的id,从小到大排序,没有的话则输出No Found 首先把每个book的信息都读取处理好,然后按照id排个序

PAT甲题题解-1004. Counting Leaves (30)-统计每层叶子节点个数+dfs

统计每层的叶子节点个数建树,然后dfs即可 #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; /* 统计每层的叶子节点个数 建树,然后dfs即可 */ const int maxn=105; int n,m; int layer[maxn]; //统计每层的叶子节点

PAT 1072. Gas Station (30)

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 o

1072. Gas Station (30)

先要求出各个加油站 最短的 与任意一房屋之间的 距离D,再在这些加油站中选出最长的D的加油站 ,该加油站 为 最优选项 (坑爹啊!).如果相同D相同 则 选离各个房屋平均距离小的,如果还是 相同,则 选 编号小的. 时间限制 200 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue A gas station has to be built at such a location that the minimum distance

1072 Gas Station (30)(30 分)

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

PAT甲题题解-1095. Cars on Campus(30)-(map+树状数组,或者模拟)

题意:给出n个车辆进出校园的记录,以及k个时间点,让你回答每个时间点校园内的车辆数,最后输出在校园内停留的总时间最长的车牌号和停留时间,如果不止一个,车牌号按字典序输出. 几个注意点: 1.如果一个车连续多次进入,只取最后一个 2.如果一个车连续多次出去,只取第一个 3.一个车可能出入校园内好几次,停留时间取总和 实际上题目就是让我们求某个时间段内的车辆总和,时间段其实就相当于一个区间,区间求和的话,很快就联想到树状数组和线段树.然而怎么将时间段和区间联系起来呢,那就存储出现在记录和询问里的所有