L3-005 垃圾箱分布 (最短路)

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

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

输入格式:

输入第一行给出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

解题思路

 跑m遍dijkstra求各个候选地点到所有居民点的最短距离,记录最短距离里的最大距离x和平均距离av。然后选择x最大的候选地点。如果存在多个,则选择av最小的,还存在多个,则选择编号小的。没有就输出No Solution。

代码如下

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#define maxn 1020
#define INF 0x3f3f3f3f
using namespace std;
int g[maxn][maxn];
int dis[15][maxn];
bool vis[maxn];
int s[15];
double av[15];
int main()
{
	int n, m, k, dist;
	cin >> n >> m >> k >> dist;
	for(int i = 1; i <= n + m; i ++){
		for(int j = 1; j <= n + m; j ++)
			g[i][j] = INF;
		g[i][i] = 0;
	} 
	for(int i = 0; i < k; i ++){
		string str1, str2;
		int d;
		cin >> str1 >> str2 >> d;
		int x, y;
		x = y = 0;
		if(str1[0] == 'G'){
			for(int i = 1; i < str1.size(); i ++)
				x = x * 10 + str1[i] - '0';
			x += n;
		}
		else {
			for(int i = 0; i < str1.size(); i ++)
				x = x * 10 + str1[i] - '0';
		}
		if(str2[0] == 'G'){
			for(int i = 1; i < str2.size(); i ++)
				y = y * 10 + str2[i] - '0';
			y += n;
		}
		else {
			for(int i = 0; i < str2.size(); i ++)
				y = y * 10 + str2[i] - '0';
		}
		g[x][y] = g[y][x] = d;
	}
	for(int i = 1; i <= m; i ++){
		for(int j = 1; j <= n + m; j ++){
			dis[i][j] = g[n + i][j];
		}
	}
	for(int i = 1; i <= m; i ++){
		memset(vis, 0, sizeof(vis));
		vis[n + i] = true;
		for(int j = 1; j < n + m; j ++){
			int minn = INF;
			int k = 0;
			for(int v = 1; v <= n + m; v ++){
				if(!vis[v] && dis[i][v] < minn){
					minn = dis[i][v];
					k = v;
				}
			}
			vis[k] = true;
			for(int v = 1; v <= n + m; v ++){
				if(!vis[v] && g[k][v] != INF && dis[i][v] > dis[i][k] + g[k][v])
					dis[i][v] = dis[i][k] + g[k][v];
			}
		}
	}
	bool flg[15] = {0};
	for(int i = 1; i <= m; i ++){
		s[i] = INF;
		for(int j = 1; j <= n; j ++){
			if(dis[i][j] < s[i])
				s[i] = dis[i][j];
			av[i] += (double)dis[i][j];
			if(dis[i][j] > dist)
				flg[i] = true;
		}
		av[i] /= (double)n;
	}
	int ans = 0;
	int maxx = -1;
	double ta = INF;
	for(int i = 1; i <= m; i ++){
		if(!flg[i]){
			if(s[i] > maxx || s[i] == maxx && av[i] < ta){
				maxx = s[i];
				ans = i;
				ta = av[i];
			}
		}
	}
	if(maxx == -1)
		cout << "No Solution" << endl;
	else {
		cout << "G" << ans << endl;
		printf("%.1lf %.1lf\n", (double)maxx, ta);
	} 
	return 0;	
}

猜你喜欢

转载自blog.csdn.net/whisperlzw/article/details/88602050
今日推荐