PAT - L3-005. 垃圾箱分布(最短路)

本文介绍了一种用于确定居民区内垃圾箱最优位置的算法。该算法考虑了居民点分布、候选地点、道路长度及最大允许距离等条件,通过计算各候选地到居民点的最短与平均距离来推荐最佳位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁都不愿意守着垃圾箱住。所以垃圾箱的位置必须选在到所有居民点的最短距离最长的地方,同时还要保证每个居民点都在距离它一个不太远的范围内。

现给定一个居民区的地图,以及若干垃圾箱的候选地点,请你推荐最合适的地点。如果解不唯一,则输出到所有居民点的平均距离最短的那个解。如果这样的解还是不唯一,则输出编号最小的地点。

输入格式:

输入第一行给出4个正整数:N(<= 103)是居民点的个数;M(<= 10)是垃圾箱候选地点的个数;K(<= 104)是居民点和垃圾箱候选地点之间的道路的条数;DS是居民点与垃圾箱之间不能超过的最大距离。所有的居民点从1到N编号,所有的垃圾箱候选地点从G1到GM编号。

随后K行,每行按下列格式描述一条道路:
P1 P2 Dist
其中P1和P2是道路两端点的编号,端点可以是居民点,也可以是垃圾箱候选点。Dist是道路的长度,是一个正整数。

输出格式:

首先在第一行输出最佳候选地点的编号。然后在第二行输出该地点到所有居民点的最小距离和平均距离。数字间以空格分隔,保留小数点后1位。如果解不存在,则输出“No Solution”。

输入样例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
输出样例1:
G1
2.0 3.3
输入样例2:
2 1 2 10
1 G1 9
2 G1 20
输出样例2:
No Solution


对m个垃圾桶位置都求一次它到其他点的最短距离,还要找出所有点中最近的距离以及平均距离,如果存在一点的最短距离>ds,则该位置不能放置垃圾桶。

然后对m个位置进行排序,先按最近距离大的排,如果最近距离相同则按平均距离小的排,再相同则按编号小的排


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 2e4 + 10;
typedef long long LL;
int n,m,k,ds,x,y,z;
int u[N],ft[N],nt[N],cost[N],sz = 0;
int dis[N];
struct node2{
    double ave,mi;
    int id;
}trash[15];
bool cmp(node2 a,node2 b){
    if(a.mi!=b.mi) return a.mi > b.mi;
    if(a.ave!=b.ave) return a.ave < b.ave;
    return a.id < b.id;
}
struct node{
    int id,cost;
    node(int a,int b){id = a; cost = b;}
    bool friend operator < (node a,node b){
        return a.cost > b.cost;
    }
};
void dij(int st){
    priority_queue<node>q;
    q.push(node(st,0));
    memset(dis,INF,sizeof dis);
    dis[st] = 0;
    while(!q.empty()){
        int pos = q.top().id,ct = q.top().cost; q.pop();
        if(ct>dis[pos]) continue;
        for(int i=ft[pos];i;i=nt[i]){
            if(dis[pos]+cost[i]<dis[u[i]]){
                dis[u[i]] = dis[pos] + cost[i];
                q.push(node(u[i],dis[u[i]]));
            }
        }
    }
    trash[st-n].mi = INF; trash[st-n].ave = 0;
    trash[st-n].id = st-n;
    for(int i=1;i<=n;i++){
        trash[st-n].mi = min(trash[st-n].mi, (double)dis[i]);
        trash[st-n].ave += dis[i];
        if(dis[i]>ds){
            trash[st-n].ave = INF;
            trash[st-n].mi = 0;
            break;
        }
    }
    if(trash[st-n].ave!=INF) trash[st-n].ave /= n;
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&k,&ds);
    for(int i=0;i<k;i++){
        char s1[10],s2[10];
        x = y = 0;
        scanf("%s%s%d",s1,s2,&z);
        if(s1[0]=='G') {
            if(s1[2]=='0') x = n+10;
            else x = n + s1[1]-'0';
        }else{
            for(int j=0;s1[j];j++){
                x = x*10 + s1[j]-'0';
            }
        }
        if(s2[0]=='G') {
            if(s2[2]=='0') y = n+10;
            else y = n + s2[1]-'0';
        }else{
            for(int j=0;s2[j];j++){
                y = y*10 + s2[j]-'0';
            }
        }
        u[++sz] = y; nt[sz] = ft[x]; ft[x] = sz; cost[sz] = z;
        u[++sz] = x; nt[sz] = ft[y]; ft[y] = sz; cost[sz] = z;
    }
    for(int i=1;i<=m;i++) dij(n+i);
    sort(trash+1,trash+1+m,cmp);
    if(trash[1].ave==INF){
        printf("No Solution\n");
    }else{
        printf("G%d\n",trash[1].id);
        printf("%.1lf %.1lf\n",trash[1].mi,trash[1].ave);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值