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 2Sample Output 1:
G1 2.0 3.3Sample Input 2:
2 1 2 10 1 G1 9 2 G1 20Sample Output 2:
No Solution
#include
#include
#include
#include
#include
using namespace std;
struct GasStation{
float mini;
float average;
int id;
};
vectorV;
bool cmp(GasStation A, GasStation B){
if (A.mini != B.mini)return A.mini > B.mini; //注意这里是>号,选最小距离的最大值
else if (A.average != B.average)return A.average < B.average;
else return A.id < B.id;
}//自定义比较函数,按照分析中的来,先最短距离的最大,再选最小的平均距离,再选最小的下标值
int main(void){
freopen("F://Temp/input.txt", "r", stdin);
int N, M, K, Ds;
scanf("%d%d%d%d", &N, &M, &K, &Ds);
int all_point = N + M;//所有站点,包括居住点和加油站
int dis[1012][1012];//*注意这里
for (int i = 1; i <= all_point; i++){
for (int j = 1; j <= all_point; j++){
dis[i][j] = -1;
}
dis[i][i] = 0;
}
for (int i = 0; i < K; i++){
int s, t, cost;
//scanf("%d%d%d", &s, &t, &cost);
string str_s, str_t;//先以字符串存储,因为可能有G加油站
cin >> str_s >> str_t >> cost;
if (str_s[0] == 'G'){
str_s = str_s.substr(1);//如果第一个字母是G,则截取掉
s = atoi(str_s.c_str()) + N;//第i个加油站Gi对应与编号(N + i)
}
else
s = atoi(str_s.c_str());//atoi(char *),把字符串变为int,因为里面是char *,所以需要str.c_str()转换
if (str_t[0] == 'G'){
str_t = str_t.substr(1);//如果第一个字母是G,则截取掉
t = atoi(str_t.c_str()) + N;//第i个加油站Gi对应与编号(N + i)
}
else
t = atoi(str_t.c_str()); //atoi(char *),把字符串变为int,因为里面是char *,所以需要str.c_str()转换
dis[s][t] = cost;
dis[t][s] = cost;
}//get the roads : input
for (int k = 1; k <= all_point; k++){
for (int i = 1; i <= all_point; i++){
for (int j = 1; j <= all_point; j++){
if (dis[i][k] == -1 || dis[k][j] == -1)continue;
if (dis[i][j] == -1 || dis[i][j] > dis[i][k] + dis[k][j]){
dis[i][j] = dis[i][k] + dis[k][j];
dis[j][i] = dis[i][j];
}
}
}
}//for-------floyd
for (int i = N + 1; i <= N + M; i++){
int sum = 0;
int min = 1 << 30;
bool isGasStation = true;//是否能作为一个加油站,即所有距离是否都在服务范围内
for (int j = 1; j <= N; j++){
if (dis[i][j] > Ds){
isGasStation = false;//距离大于服务范围,不能合格
break;
}
sum += dis[i][j];
if (min > dis[i][j])
min = dis[i][j];
}
if (isGasStation){
GasStation tmp;
tmp.id = i - N;
tmp.mini = min * 1.0;
tmp.average = sum * 1.0 / N;
V.push_back(tmp);//把合格的加油站都记录放入vector中
}
}
if (V.size() == 0){
printf("No Solution\n");
}//注意边界条件,当V中无解时输出No Solution
else{
sort(V.begin(), V.end(), cmp);
printf("G%d\n%.1f %.1f\n", V[0].id, V[0].mini, V[0].average);
}
return 0;
}
先是用floid做的,但是太耗时了,案例5运行超时了。改写了代码为dijkstra。
#include
#include
#include
#include
#include
#include//memset()
using namespace std;
struct GasStation{
float mini;
float average;
int id;
};
vectorV;
bool cmp(GasStation A, GasStation B){
if (A.mini != B.mini)return A.mini > B.mini; //注意这里是>号,选最小距离的最大值
else if (A.average != B.average)return A.average < B.average;
else return A.id < B.id;
}//自定义比较函数,按照分析中的来,先最短距离的最大,再选最小的平均距离,再选最小的下标值
bool mark[1012];
int Dis[1012];//用来存放加油站到各个居住点的距离
//void Dij(int start, int ds[][1012],int N,int M){//这种也是可以的,但是不能int **ds或int ds[][]
void Dij(int start, int (*ds)[1012], int N, int M){//当以二位数组作为参数的时候,可以用上面或这里的两种方式,注意一定要指明纵坐标值
mark[start] = true;
int newP = start;
Dis[start] = 0;
for (int j = 1; j <= N + M; j++){//一共进行N + M次循环就能找出一个加油站出发的所有距离
for (int i = 1; i <= N + M; i++){
if (mark[i] || ds[newP][i] == -1)continue;
else if (Dis[i] == -1 || Dis[i] > Dis[newP] + ds[newP][i]){
Dis[i] = Dis[newP] + ds[newP][i];
}
}
int min = 1 << 30;
for (int i = 1; i <= N + M; i++){
if (mark[i] || Dis[i] == 0 || Dis[i] == -1)continue;
if (Dis[i] < min){
min = Dis[i];
newP = i;
}
}
mark[newP] = true;
}
for (int j = 1; j <= N + M; j++){//把
if (start != j){
ds[start][j] = Dis[j];
ds[j][start] = Dis[j];
}
}
}
int main(void){
freopen("F://Temp/input.txt", "r", stdin);
int N, M, K, Ds;
scanf("%d%d%d%d", &N, &M, &K, &Ds);
int all_point = N + M;//所有站点,包括居住点和加油站
int dis[1012][1012];
for (int i = 1; i <= all_point; i++){
for (int j = 1; j <= all_point; j++){
dis[i][j] = -1;
}
dis[i][i] = 0;
}
for (int i = 0; i < K; i++){
int s, t, cost;
//scanf("%d%d%d", &s, &t, &cost);
string str_s, str_t;//先以字符串存储,因为可能有G加油站
cin >> str_s >> str_t >> cost;
if (str_s[0] == 'G'){
str_s = str_s.substr(1);//如果第一个字母是G,则截取掉
s = atoi(str_s.c_str()) + N;//第i个加油站Gi对应与编号(N + i)
}
else
s = atoi(str_s.c_str());//atoi(char *),把字符串变为int,因为里面是char *,所以需要str.c_str()转换
if (str_t[0] == 'G'){
str_t = str_t.substr(1);//如果第一个字母是G,则截取掉
t = atoi(str_t.c_str()) + N;//第i个加油站Gi对应与编号(N + i)
}
else
t = atoi(str_t.c_str()); //atoi(char *),把字符串变为int,因为里面是char *,所以需要str.c_str()转换
dis[s][t] = cost;
dis[t][s] = cost;
}//get the roads : input
/* for (int k = 1; k <= all_point; k++){
for (int i = 1; i <= all_point; i++){
for (int j = 1; j <= all_point; j++){
if (dis[i][k] == -1 || dis[k][j] == -1)continue;
if (dis[i][j] == -1 || dis[i][j] > dis[i][k] + dis[k][j]){
dis[i][j] = dis[i][k] + dis[k][j];
dis[j][i] = dis[i][j];
}
}
}
}//for-------floyd */
for (int i = N + 1; i <= N + M; i++){
memset(mark, false, sizeof(mark));
memset(Dis, -1, sizeof(Dis));
Dij(i, dis,N,M);
}//多源最短路径,需要循环,以及初始化
for (int i = N + 1; i <= N + M; i++){
int sum = 0;
int min = 1 << 30;
bool isGasStation = true;//是否能作为一个加油站,即所有距离是否都在服务范围内
for (int j = 1; j <= N; j++){
if (dis[i][j] > Ds){
isGasStation = false;//距离大于服务范围,不能合格
break;
}
sum += dis[i][j];
if (min > dis[i][j])
min = dis[i][j];
}
if (isGasStation){
GasStation tmp;
tmp.id = i - N;
tmp.mini = min * 1.0;
tmp.average = sum * 1.0 / N;
V.push_back(tmp);//把合格的加油站都记录放入vector中
}
}
if (V.size() == 0){
printf("No Solution\n");
}//注意边界条件,当V中无解时输出No Solution
else{
sort(V.begin(), V.end(), cmp);
printf("G%d\n%.1f %.1f\n", V[0].id, V[0].mini, V[0].average);
}
return 0;
}
这里注意一下二维数组作为参数的注意点,可以参考: http://blog.csdn.net/caryaliu/article/details/8131408