大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁都不愿意守着垃圾箱住。所以垃圾箱的位置必须选在到所有居民点的最短距离最长的地方,同时还要保证每个居民点都在距离它一个不太远的范围内。
现给定一个居民区的地图,以及若干垃圾箱的候选地点,请你推荐最合适的地点。如果解不唯一,则输出到所有居民点的平均距离最短的那个解。如果这样的解还是不唯一,则输出编号最小的地点。
输入格式:
输入第一行给出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
注意数据的存储,输入道路两端点的编号要用string来接收,利用atoi()函数将字符串转为int存储
对于G1、G2等垃圾箱的编号,也转为int,新编号 = 垃圾箱的编号(不要G字符) + 居民的个数
然后迪杰斯特拉即可,但要注意,由于要进行多次迪杰斯特拉,因此初始化时要在迪杰斯特拉函数内,每进行一次迪杰斯特拉都要初始化一次,我刚开始写这道题时由于没有在迪杰斯特拉函数内部对vis[]函数初始化,运行答案正确,提交时只得了两分,找了好久的Bug
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 10001;
const int INF = 0x3f3f3f;
int a[MAXN][MAXN];
int dist[MAXN];
int n,m,k,d;
struct node{
int id;
double minDist,avgDist;
}ans[11];
int cnt = 0;
void djkstla(int s){
/* 由于djkstla函数不只执行一次, 因此每次都要初始化标记数组 */
bool vis[MAXN]={false};
fill(dist,dist+MAXN,INF);
dist[s] = 0;
for(int i=1;i<=n+m;i++){
int min = INF,u = -1;
for(int j=1;j<=n+m;j++){
if(vis[j]==false && dist[j]<min){
min = dist[j];
u = j;
}
}
if(u==-1) return ;
vis[u] = true;
for(int j=1;j<=n+m;j++){
if(vis[j]==false && dist[j] > dist[u] + a[u][j]){
dist[j] = dist[u] + a[u][j];
}
}
}
double sumD = 0;
int minD = INF;
for(int i=1;i<=n;i++){
if(dist[i] > d) return ;
minD = min(minD,dist[i]);
sumD += dist[i];
}
ans[cnt].id = s;
ans[cnt].minDist = minD;
ans[cnt].avgDist = sumD / n;
cnt++;
}
int cmp(node a,node b){
if(a.minDist!=b.minDist){
return a.minDist > b.minDist;
}else if(a.avgDist!=b.avgDist){
return a.avgDist < b.avgDist;
}else{
return a.id < b.id;
}
}
int main(){
string s1,s2;
int num;
cin>>n>>m>>k>>d;
for(int i=1;i<=n+m;i++){ //初始化a数组
for(int j=1;j<=n+m;j++){
if(i!=j) a[i][j] = a[j][i] = INF;
else a[i][j] = 0;
}
}
for(int i=0;i<k;i++){
int n1=0,n2=0;
cin>>s1>>s2>>num;
if(s1[0] == 'G') {
s1 = s1.substr(1);
n1 = n;
}
n1 += atoi(s1.c_str());
if(s2[0] == 'G'){
s2 = s2.substr(1);
n2 = n;
}
n2 += atoi(s2.c_str());
a[n1][n2] = a[n2][n1] = num;
}
for(int i=n+1;i<=n+m;i++){
djkstla(i);
}
sort(ans,ans+cnt,cmp);
if(cnt!=0){
printf("G%d\n",ans[0].id-n);
printf("%.1f %.1f\n",ans[0].minDist,ans[0].avgDist);
}else{
printf("No Solution\n");
}
return 0;
}