大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁都不愿意守着垃圾箱住。所以垃圾箱的位置必须选在到所有居民点的最短距离最长的地方,同时还要保证每个居民点都在距离它一个不太远的范围内。
现给定一个居民区的地图,以及若干垃圾箱的候选地点,请你推荐最合适的地点。如果解不唯一,则输出到所有居民点的平均距离最短的那个解。如果这样的解还是不唯一,则输出编号最小的地点。
输入格式:
输入第一行给出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
Dijkstra算法,将每个垃圾桶待选点作为源点跑一遍Dijkstra,再根据题意选取结果即可
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1e4 + 10;
int dist[N],vis[N];
int n,m,k,d;
struct node{
double min_distance;
int num;
double average_dist;
};
vector<node> vect;
typedef pair<int,int> PII;
priority_queue<PII,vector<PII>,greater<PII>> q;
vector<int> g[1011];
vector<int> weight[1011];
void dijkstra(int s){
memset(dist,0x3f,sizeof dist);
memset(vis,0,sizeof vis);
dist[s] = 0;
q.push({0,s});
while(!q.empty()){
PII t = q.top();
q.pop();
int u = t.second;
vis[u] = 1;
for (int j = 0;j < g[u].size(); ++j){
int v = g[u][j];
if (vis[v] == 0 && dist[v] > dist[u] + weight[u][j]){
dist[v] = dist[u] + weight[u][j];
q.push({dist[v],v});
}
}
}
}
bool cmp(node a,node b){
if (a.min_distance != b.min_distance) return a.min_distance > b.min_distance;
if (a.average_dist != b.average_dist) return a.average_dist < b.average_dist;
return a.num < b.num;
}
int main(){
int id1,id2,distance;
cin>>n>>m>>k>>d;
string line;
getchar();
while(k--){
getline(cin,line);
for (int i = 0; i < line.size(); ++i) if (line[i] == 'G') line[i] = '-';
sscanf(line.c_str(),"%d%d%d",&id1,&id2,&distance);
if (id1 < 0) id1 = n + -1 * id1;
if (id2 < 0) id2 = n + -1 * id2;
g[id1].push_back(id2),g[id2].push_back(id1);
weight[id1].push_back(distance),weight[id2].push_back(distance);
}
int error_cnt = 0,flag;
for (int i = n + 1; i <= n + m; ++i){
dijkstra(i);
flag = 0;
int min_distance = 0x3f3f3f3f;double sum = 0;
for (int j = 1; j <= n; ++j){
min_distance = min(min_distance,dist[j]);
if (dist[j] <= d)
sum += dist[j];
else {
flag = 1;
break;
}
}
error_cnt += flag;
if (flag == 0){
vect.push_back({min_distance,i,(sum * 1.0)/n});
}
}
sort(vect.begin(),vect.end(),cmp);
if (error_cnt != m){
cout<<'G'<<vect[0].num - n<<endl;
printf("%.1f %.1f",vect[0].min_distance,vect[0].average_dist + 0.005);
}else puts("No Solution");
return 0;
}
本文介绍了一种基于Dijkstra算法的最优垃圾箱选址方案。在考虑居民点与垃圾箱候选地点的距离约束下,通过计算各候选点到所有居民点的最短路径,选出满足条件的最适位置。若存在多个解,则优选平均距离最小且编号最小的地点。

850

被折叠的 条评论
为什么被折叠?



