L3-005 垃圾箱分布 - spfa

L3-005 垃圾箱分布 (30 分)

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

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

输入格式:

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

随后K行,每行按下列格式描述一条道路:

P1 P2 Dist

其中P1P2是道路两端点的编号,端点可以是居民点,也可以是垃圾箱候选点。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

思路:

这个题的题意有点绕,就是以每个垃圾箱为源点求出到居民点的最短距离。每个垃圾箱到各个居民点的距离里的最小值记录一下,因为居民都不愿意里垃圾箱太近,所以我们求的是各个垃圾箱最小值的最大值= =!

而这个垃圾箱到居民的点又不能小于Ds

我在cb上调试的时候,样例结果是“3.2”而不是“3.3”,结果提交上去AC了= =,证明不同的编译器,对于浮点数显示的结果是不同的。

也可以这样,手动四舍五入保留1位小数:(x*10.0+0.5)/10.0

若是四舍五入保留2位小数:(x*100.0+0.5)/100.0

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<int,int>P;
const int INF=4e8;
const int N=1015,mod=32767;
const double eps=1e-9;
char s1[5],s2[5];
int n,m,cnt,head[N],vis[N],dis[N];
;
struct A{
    int to,nex,cost;
}edge[20015];

struct B{
    int seq,aD,minD;
};
vector<B>ans;

bool cmp(B a,B b){
    if(a.minD!=b.minD)return a.minD>b.minD;
    else if(a.aD!=b.aD)return a.aD<b.aD;
    else return a.seq<b.seq;
}

void add(int from,int to,int cost){
    edge[cnt].cost=cost;
    edge[cnt].to=to;
    edge[cnt].nex=head[from];
    head[from]=cnt++;
}

int get_num(char s[]){
    int ans=0,tmp=1;
    for(int i=strlen(s)-1;i>=0;i--){
        if(s[i]=='G'){
            ans+=n;
            break;
        }
        ans+=(s[i]-'0')*tmp;
        tmp*=10;
    }
    return ans;
}

void spfa(int s){
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n+m;i++){
        dis[i]=INF;
    }
    queue<int>Q;
    vis[s]=1;
    dis[s]=0;
    Q.push(s);
    while(!Q.empty()){
        int v=Q.front();Q.pop();
        vis[v]=0;
        for(int i=head[v];i!=-1;i=edge[i].nex){
            int u=edge[i].to;
            if(dis[u]>dis[v]+edge[i].cost){
                dis[u]=dis[v]+edge[i].cost;
                if(!vis[u]){
                    vis[u]=1;
                    Q.push(u);
                }
            }
        }
    }
}

int judge(int id,int ds){
    int mymin=INF;
    int sum=0;
    for(int i=1;i<=n;i++){
        if(dis[i]>ds)return 0;
        sum+=dis[i];
        mymin=min(mymin,dis[i]);
    }
    ans.push_back({id,sum,mymin});
    return 1;
}

int main(){
    int k,ds,x;
    scanf("%d%d%d%d",&n,&m,&k,&ds);
    memset(head,-1,sizeof(head));
    for(int i=1;i<=k;i++){
        scanf("%s%s%d",s1,s2,&x);
        int a=get_num(s1);
        int b=get_num(s2);
        add(a,b,x);
        add(b,a,x);
    }
    int flag=0;
    for(int i=1;i<=m;i++){
        spfa(i+n);
        flag=judge(i,ds);
    }
    if(!flag){
        printf("No Solution\n");
    }
    else{
        sort(ans.begin(),ans.end(),cmp);
        printf("G%d\n",ans[0].seq);
        printf("%.1f %.1f\n",1.0*ans[0].minD,1.0*ans[0].aD/n);
    }
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值