L3-005 垃圾箱分布 (30 分)
大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁都不愿意守着垃圾箱住。所以垃圾箱的位置必须选在到所有居民点的最短距离最长的地方,同时还要保证每个居民点都在距离它一个不太远的范围内。
现给定一个居民区的地图,以及若干垃圾箱的候选地点,请你推荐最合适的地点。如果解不唯一,则输出到所有居民点的平均距离最短的那个解。如果这样的解还是不唯一,则输出编号最小的地点。
其中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
分析:
看到这一题的第一想法是最小生成树和dij最短路径,后来想想,题目只要求每一个居民点和垃圾桶相连即可,所以选择最短路径。
之后对每一个垃圾桶选择点都进行dij,在dij数组的最大值不大于ds的情况下,选择dij的数组的最小值最大的,如果最小值一样就选择和最小的。
这一题给我的反思就是:在选择最大最小的时候,有关变量也一定要及时更新,不然会出现很难找到的错误,浪费时间去修改代码。
over
#include<iostream>
#include<string.h>
using namespace std;
const int INF = (1<<30) -2;
int dij[1015];
int way[1015][1015];
int book[1015];
int n, m, k, ds;
int main() {
fill(way[0], way[0] + 1015 * 1015, INF);
cin >> n >> m >> k >> ds;
string s1, s2;
int key;
for (int i = 1; i <= k; i++) {
int num1, num2;
cin >> s1 >> s2 >> key;
num1 = s1[0] == 'G' ? (s1[1] - '0' + n) : (s1[0] - '0');
num2 = s2[0] == 'G' ? (s2[1] - '0' + n) : (s2[0] - '0');
way[num1][num2] = key;
way[num2][num1] = key;
}
int ans_max = -1;
int ans_id = 0;
int ans_sum = 0;
for (int i = 1; i <= m; i++) { //枚举每一个候选点
//dij部分
fill(book, book + 1011, 0);
fill(dij,dij + 1011,INF);
dij[i + n] = 0;
for (int j = 1; j <= n + m; j++) {
int x = 0,minn = INF;
for (int z = 1; z <= n + m; z++) {
if (book[z] == 0 && minn > dij[z]) {
x = z;
minn = dij[z];
}
}
if(x == 0) break;
book[x] = 1;
for (int z = 1; z <= n + m; z++) {
if(book[z] == 1 || way[x][z] == INF) continue;
dij[z] = min(dij[z], dij[x] + way[x][z]);
}
}
//答案处理部分
int tmin = INF, tmax = -1,sum = 0;
for (int j = 1; j <= n; j++) {
tmin = min(tmin, dij[j]);
tmax = max(tmax, dij[j]);
sum += dij[j];
}
if(tmax <= ds && tmin > ans_max) { //不太远 不太近
ans_max = tmin;
ans_id = i;
ans_sum = sum;
} else if(tmax <= ds && tmin == ans_max) { //如果一样进 选择 sum最小的
if (sum < ans_sum) {
ans_id = i;
ans_sum = sum;
}
}
}
if(ans_id != 0) {
float ans1 = ans_max * 1.0;
float ans2 = ans_sum * 1.0 / n + 0.5;
cout << "G" << ans_id << endl;
printf("%.1f %.1f", ans1, ans2);
} else {
cout << "No Solution";
}
return 0;
}