1. 程式人生 > >PAT (Advanced Level) Practice 1072 Gas Station (30 分)

PAT (Advanced Level) Practice 1072 Gas Station (30 分)

1072 Gas Station (30 分)

A gas station has to be built at such a location that the minimum distance between the station and any of the residential housing is as far away as possible. However it must guarantee that all the houses are in its service range.

Now given the map of the city and several candidate locations for the gas station, you are supposed to give the best recommendation. If there are more than one solution, output the one with the smallest average distance to all the houses. If such a solution is still not unique, output the one with the smallest index number.

Input Specification:

Each input file contains one test case. For each case, the first line contains 4 positive integers: N (≤10​3​​), the total number of houses; M (≤10), the total number of the candidate locations for the gas stations; K (≤10​4​​), the number of roads connecting the houses and the gas stations; and D​S​​, the maximum service range of the gas station. It is hence assumed that all the houses are numbered from 1 to N, and all the candidate locations are numbered from G

1 to GM.

Then K lines follow, each describes a road in the format

P1 P2 Dist

where P1 and P2 are the two ends of a road which can be either house numbers or gas station numbers, and Dist is the integer length of the road.

Output Specification:

For each test case, print in the first line the index number of the best location. In the next line, print the minimum and the average distances between the solution and all the houses. The numbers in a line must be separated by a space and be accurate up to 1 decimal place. If the solution does not exist, simply output No Solution

.

Sample Input 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

Sample Output 1:

G1
2.0 3.3

Sample Input 2:

2 1 2 10
1 G1 9
2 G1 20

Sample Output 2:

No Solution

題目大意:

給出居民和加油站的所有路線和距離,要求加油站離所有居民的距離在一定範圍內。滿足此條件時,加油站離居民的最近距離越遠越好。如果最近距離相同,加油站與居民的平均距離越近越好。如果平均距離也相同,輸出編號最小的加油站。

解題思路:

Dijkstra最短路徑演算法。

為區別居民地與加油站,以字串形式讀入,居民地編號不變,加油站的編號改為原編號+居民數。以此建圖。

因為要求最佳加油站,對每個加油站都要進行最短路徑求解並做比較(外迴圈)。在求某個加油站的最短路徑時,需要先對dis陣列和book陣列初始化(內迴圈的第一個迴圈),然後進行最短路徑求解(內迴圈的第二個迴圈),最後更新最近距離和平均距離(內迴圈的第三個迴圈)。在單源最短路徑求解的時候,內部又有一些迴圈。

注意事項:

1、加油站的編號優化,可以從1000以後開始編號,也可以從n以後開始編號,後者更方便。

2、求編號值,string 轉 int 用到 stoi(string s)函式。當字串中含非數字的字元時,要過濾,用到s.erase(s.begin())。

3、求最佳加油站的時候,注意各個迴圈之間的關係,不要搞錯。

4、因為所有距離都要小於額定值才算,所以在求單源最短路徑的時候可以進行剪枝。

5、需要進行多次單源最短路徑求解,每次求解前不要忘記初始化。

6、有可能沒有最佳加油站,注意判斷條件。這裡採用初始化 ans_id= n+m+1 的方式,如果最後ans_id值不變,說明沒有這樣的加油站,輸出"No Solution"。

原始碼:

#include<iostream>
#include<string>
#include<stdlib.h>
using namespace std;
const int inf = 99999999;
int e[1020][1020], book[1020], dis[1020];
int main()
{
	int n, m, k, ds;
	int i, j;
	string s1, s2;
	int p1, p2, dist;

	scanf("%d %d %d %d", &n, &m, &k, &ds);
	for (i = 1; i <= n + m; i++)
	{
		for (j = 1; j <= n + m; j++)
			if (i == j)e[i][j] = 0;
			else e[i][j] = inf;
	}
	for (i = 0; i < k; i++)
	{
		cin >> s1 >> s2 >> dist;
		if (s1[0] != 'G')p1 = stoi(s1);
		else
		{
			s1.erase(s1.begin());
			p1 = n + stoi(s1);
		}
		if (s2[0] != 'G')p2 = stoi(s2);
		else
		{
			s2.erase(s2.begin());
			p2 = n + stoi(s2);
		}
		e[p1][p2] = e[p2][p1] = dist;
	}
	//Dijkstra
	int g, h, flag, ans_id = n + m + 1;
	double ans_min = 0, ans_avg = 0, temp_min = inf, temp_avg = 0;
	for (j = n + 1; j <= n + m; j++)
	{
		for (i = 1; i <= n + m; i++)
		{
			book[i] = 0;
			dis[i] = inf;
		}
		dis[j] = 0;
		flag = 0;
		for (h = 1; h <= n + m; h++)
		{
			int u, idmin=j, dmin = inf;
			for (i = 1; i <= n + m; i++)
			{
				if (book[i] == 0 && dis[i] < dmin)
				{
					idmin = i;
					dmin = dis[i];
				}
			}
			if (dmin > ds&&idmin <= n)
			{
				flag = 1; break;
			}
			book[idmin] = 1;
			for (i = 1; i <= n+m; i++)
			{
				if (book[i] == 0 && dis[i] > dis[idmin] + e[idmin][i])
					dis[i] = dis[idmin] + e[idmin][i];
			}
		}
//		printf("end: %d\n", j);
		if (flag == 0)
		{
			temp_avg = 0;
			temp_min = inf;
			for (i = 1; i <= n; i++)
			{
				temp_avg += dis[i];
				if (temp_min > dis[i])temp_min = dis[i];
			}
			if (ans_min<temp_min || ans_min == temp_min && ans_avg>temp_avg)
			{
				ans_id = j;
				ans_min = temp_min;
				ans_avg = temp_avg;
			}
		}
	}
	if (ans_id == n + m + 1)printf("No Solution");
	else
	{
		printf("G%d\n%.1lf %.1lf", ans_id-n, ans_min, 1.0 * ans_avg / n);
	}
	system("pause");
	return 0;
}