L3-005 垃圾箱分布 (30 分)
大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁都不愿意守着垃圾箱住。所以垃圾箱的位置必须选在到所有居民点的最短距离最长的地方,同时还要保证每个居民点都在距离它一个不太远的范围内。
现给定一个居民区的地图,以及若干垃圾箱的候选地点,请你推荐最合适的地点。如果解不唯一,则输出到所有居民点的平均距离最短的那个解。如果这样的解还是不唯一,则输出编号最小的地点。
输入格式:
输入第一行给出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
思路:
这个题的题意有点绕,就是以每个垃圾箱为源点求出到居民点的最短距离。每个垃圾箱到各个居民点的距离里的最小值记录一下,因为居民都不愿意里垃圾箱太近,所以我们求的是各个垃圾箱最小值的最大值= =!
而这个垃圾箱到居民的点又不能小于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);
}
}