【题意】
找一个到所有房屋最短距离最远,平均距离最近,且覆盖所有房屋的加油站
【思路】
把住房和加油站都视作普通节点,对每个加油站用一次Dijkstra算法即可
【注意点】
此题Dijkstra算法中可以不用遍历到每个点,只要把所有房屋都访问到了就可以了,即使有些加油站访问不到或者超出了服务范围也不要紧。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
using namespace std;
#define MAXIMUM 0x0fffffff
int n,m,k,ds;
vector<bool> visited;
vector<int> dist;
vector<vector<int>> weight;
typedef struct{
int index;
int minDist;
float avgDist;
}gasStation;
bool cmp(gasStation g1, gasStation g2){
if(g1.minDist>g2.minDist){
return 1;
}
else if(g1.minDist==g2.minDist && g1.avgDist<g2.avgDist){
return 1;
}
else if(g1.minDist==g2.minDist && g1.avgDist==g2.avgDist && g1.index<g2.index){
return 1;
}
else{
return 0;
}
}
int lable2index(string lable){
int index = 0;
if(lable[0]=='G'){
for(int i=1; i<lable.length(); i++){
index = index*10+lable[i]-'0';
}
index += n-1;
}
else{
for(int i=0; i<lable.length(); i++){
index = index*10+lable[i]-'0';
}
index--;
}
return index;
}
int main(int argc, char const *argv[])
{
cin >> n >> m >> k >> ds;
visited.resize(n+m);
dist.resize(n+m);
weight.resize(n+m,vector<int>(n+m));
for(int i=0; i<n+m; i++){
for(int j=0; j<=i; j++){
if(i==j){
weight[i][j] = 0;
}
else{
weight[i][j] = weight[j][i] = MAXIMUM;
}
}
}
//0~n-1 :residential housing
//n~n+m-1 :gas station
for(int i=0; i<k; i++){
string ends[2];
int d,index[2];
cin >> ends[0] >> ends[1] >> d;
index[0] = lable2index(ends[0]);
index[1] = lable2index(ends[1]);
weight[index[0]][index[1]] = weight[index[1]][index[0]] = d;
}
vector<gasStation> stations;
//Dijkstra
for(int gasIndex=n; gasIndex<n+m; gasIndex++){
visited.assign(n+m,0);
dist.assign(n+m,MAXIMUM);
visited[gasIndex] = 1;
dist[gasIndex] = 0;
bool valid = 1;
int minDist = MAXIMUM;
float avgDist = 0.0;
int cnt = n;
int index = gasIndex;
//并不需要把每个节点都遍历到,只需要把n个城市遍历到即可
while(cnt){
int min = MAXIMUM;
int nextIndex;
for(int j=0; j<n+m; j++){
if(!visited[j]){
if(dist[index]+weight[index][j]<dist[j]){
dist[j] = dist[index]+weight[index][j];
}
if(dist[j]<min){
min = dist[j];
nextIndex = j;
}
}
}
if(min>ds){
valid = 0;
break;
}
index = nextIndex;
visited[index] = 1;
//编号小于n的点代表住房
if(index<n){
cnt--;
if(dist[index]<minDist){
minDist = dist[index];
}
avgDist += dist[index];
}
}
avgDist /= n;
if(valid){
gasStation tmp;
tmp.index = gasIndex;
tmp.minDist = minDist;
tmp.avgDist = avgDist;
stations.push_back(tmp);
}
}
if(stations.empty()){
cout << "No Solution";
}
else{
sort(stations.begin(),stations.end(),cmp);
cout << 'G' << stations[0].index-n+1 << endl;
printf("%d.0 %.1f", stations[0].minDist, stations[0].avgDist);
}
system("pause");
return 0;
}