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 (<= 103), the total number of houses; M (<= 10), the total number of the candidate locations for the gas stations; K (<= 104), the number of roads connecting the houses and the gas stations; and DS, 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 G1 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
1 #include<cstdio> 2 #include<iostream> 3 #include<vector> 4 #include<algorithm> 5 #include<string.h> 6 using namespace std; 7 const int INF = 100000000; 8 int G[1011][1011], visit[1011], dst[1011]; 9 int station = -1, maxLen = -1, sum = INF; 10 double average = 0; 11 int N, M, K, Ds; 12 int str2num(char str[]){ 13 int num = 0, P = 1; 14 if(str[0] == 'G'){ 15 for(int i = strlen(str) - 1; i > 0; i--){ 16 num += (str[i] - '0') * P; 17 P *= 10; 18 } 19 20 return num + N; 21 }else{ 22 for(int i = strlen(str) - 1; i >= 0; i--){ 23 num += (str[i] - '0') * P; 24 P *= 10; 25 } 26 return num; 27 } 28 } 29 void dijkstra(int s){ 30 fill(visit, visit + 1011, 0); 31 fill(dst, dst + 1011, INF); 32 dst[s] = 0; 33 for(int i = 1; i <= N + M; i++){ 34 int u = -1, minLen = INF; 35 for(int j = 1; j <= N + M; j++){ 36 if(visit[j] == 0 && dst[j] < minLen){ 37 minLen = dst[j]; 38 u = j; 39 } 40 } 41 if(u == -1) 42 return; 43 visit[u] = 1; 44 for(int j = 1; j <= N + M; j++){ 45 if(visit[j] == 0 && G[u][j] != INF){ 46 if(G[u][j] + dst[u] < dst[j]){ 47 dst[j] = G[u][j] + dst[u]; 48 } 49 } 50 } 51 } 52 } 53 int main(){ 54 scanf("%d%d%d%d", &N, &M, &K, &Ds); 55 char str1[20], str2[20]; 56 int temp; 57 fill(G[0], G[0] + 1011*1011, INF); 58 for(int i = 0; i < K; i++){ 59 scanf("%s %s %d", str1, str2, &temp); 60 int p1 = str2num(str1); 61 int p2 = str2num(str2); 62 G[p1][p2] = G[p2][p1] = temp; 63 } 64 for(int i = N + 1; i <= N + M; i++){ 65 dijkstra(i); 66 int minFind = INF, sumTemp = 0; 67 for(int j = 1; j <= N; j++){ 68 sumTemp += dst[j]; 69 if(dst[j] == INF || dst[j] > Ds){ 70 minFind = INF; 71 break; 72 } 73 if(dst[j] < minFind){ 74 minFind = dst[j]; 75 } 76 } 77 if(minFind != INF){ 78 if(minFind > maxLen){ 79 maxLen = minFind; 80 sum = sumTemp; 81 station = i; 82 }else if(minFind == maxLen && sumTemp < sum){ 83 maxLen = minFind; 84 sum = sumTemp; 85 station = i; 86 } 87 } 88 } 89 if(station == -1) 90 printf("No Solution "); 91 else{ 92 double betw = maxLen * 1.0; 93 average = (double)sum / (double)N; 94 printf("G%d %.1f %.1f", station - N, betw, average); 95 } 96 cin >> N; 97 return 0; 98 }
总结:
1、题意:有M个待选位置,选其中一个建造加油站。选择原则是该加油站应该使得距离它最近的房屋的距离最大。如果有多个待选方案,则选择使油站到所有房屋的平均距离最小。 即先对每一个待选位置做一次dijkstra,求出它到每一个房屋的最短路,在这之中选择最小的记为MINi,该位置到所有房屋的平均距离记为AVGi。 对所有的带选位置对应的MINi,选择一个最大的。如果有多个最大值,则选择到最小的AVGi的那个。
2、由于M个待选点虽然不是房屋且不计入最短路内,但它作为一个节点也有联通其它房屋的作用。所以在dijkstra时需要把它们算在内。但在找MINi与AVGi时,它们需要被排除。
3、计算均值且比较大小有误差,可以先用sum和代替,在最后输出时再算均值。
4、由于题目输入的数据有纯数字,也有G和数字。所以统一按照字符串读入再转为数字。对于普通房屋,编号1到N,加油站编号从N+1开始,即G1、G2的编号为N+1, N+2。
5、对于这类构造数据很麻烦的题,在调试时尽可能想最简单的测试数据以及边界数据。比如只有一个house和一个待选点。