PAT-练习集-L3-005. 垃圾箱分布

//传送门:https://www.patest.cn/submissions/2864084 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
using namespace std;
#define N 1015
#define M 10015
#define INF 0x3f3f3f3f 
char s1[6],s2[6]; 
int head[N];
struct edge
{
  int v,dis,next;
}e[M<<1];
struct node
{
  float len,average;   // len 垃圾箱 距离居名点的最短距离 , average 垃圾箱 距离居名点的平均距离 
  bool flag;           // 垃圾箱 到 居名点的距离 是否有 超过 限制的最长距离 
}no[N];
bool has[N];           // spfa中 标记 在队列中 
int d[N];              // 居民点 距离 垃圾箱 的长度 
int n,m,k,longest;
inline void spfa(int st)
{
  memset(has,0,sizeof(has));
  memset(d,INF,sizeof(d));   
  d[st] = 0;            // 初始点 的 距离 设为 0 
    queue<int>que;
    que.push(st);
    while(!que.empty()){
      int w = que.front(); que.pop();
      has[w] = 0;                           
      for(int i=head[w];~i;i=e[i].next){   
        int v = e[i].v;
        if(d[v]<=d[w]+e[i].dis) continue;  // 根据 每个居民点 距离 第 st - n 个垃圾箱的距离来更新 
        d[v] = d[w] + e[i].dis; 
        if(has[v]) continue;
        que.push(v);
        has[v] = 1;
      }
    }
    long long  sum = 0;                    //  垃圾箱 距离所有居名点的总距离 
    int minnum = INF;                      //  垃圾箱 到所有居名点的最短距离 
    bool flag = 0;
    for(int i=1;i<=n;i++){
      if(d[i]>longest){                    //  超出限制的距离 
        flag = 1;
        break;
      }
      minnum = min(minnum,d[i]);
      sum += d[i];
    }
    no[st-n].flag = flag;
    if(flag) return;
    no[st-n].len = minnum*1.;
    no[st-n].average = sum*1./n;
}
int main()
{
  scanf("%d%d%d%d",&n,&m,&k,&longest);
  int tot = 0;
  memset(head,-1,sizeof(head));
   while(k--){
     scanf("%s%s",s1,s2);
      int a,b,c;
     if(s1[0]=='G'){
     if(strlen(s1)==3) a=10+n;             //  G10   垃圾箱的编号接在第n个居民点之后  Gm 的编号为 n+m 
     else a=s1[1]-'0'+n;                    
     } 
     else a=atoi(s1);
     if(s2[0]=='G'){
     if(strlen(s2)==3) b=10+n;
     else b=s2[1]-'0'+n;  
     } 
     else b=atoi(s2);
     scanf("%d",&c);
    e[tot].v = b;
    e[tot].dis = c;
    e[tot].next = head[a];
    head[a] = tot++;  
      e[tot].v = a;
      e[tot].dis = c;
      e[tot].next = head[b];
      head[b] = tot++;
   }
   for(int i=1;i<=m;i++){                 // 每个垃圾箱 做一次 spfa 
     spfa(n+i);
   }
   bool flag = 0; 
   float a=0,b=INF;                       // a记录(垃圾箱中)最长的(每个垃圾箱距离居名点的)最短路 ,b 记录 平均距离 
   //cout<<"*"<<b<<endl;
   int ansnum;
   for(int i=1;i<=m;i++){                 // 遍历 每个 垃圾箱 
     if(!no[i].flag){                     // 如果满足,尝试更新答案 
       flag = 1;                          // 更新过,表示有答案 
       if(no[i].len>a){                   // 记录(垃圾箱中)最长的(每个垃圾箱距离居名点的)最短路 
         a = no[i].len;
         b = no[i].average;
         ansnum = i;
       }else if(no[i].len == a && no[i].average < b){  // 如果 最短路相同,比较平均距离 
         b = no[i].average;
         ansnum = i;
       } 
     }
   }
   if(flag){
     printf("G%d\n",ansnum);
     printf("%.1f %.1f",a,b);
   }else  printf("No Solution");
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值