1072 Gas Station (dijkstra(无start与end 多次使用dijkstra))

本文介绍了一种用于确定城市中最佳加油站位置的算法,目标是最小化住宅区与加油站之间的平均距离,同时确保所有住宅都在服务范围内。通过Dijkstra算法计算不同候选地点到各住宅的最短路径,选择平均距离最小且最远距离最大的地点作为最优位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

 

本题思路:

         本题主要是有多个加油站n,与多个房屋m,题意是找到一个加油站与所有房屋最近的道路(这条道路同时是所有加油站中最远的一条)(如果存在相同的最短路径,就判断加油站到(所有)的房屋相加最短的平均距离(不需要判断路径的结点个数))因此可以对每个加油站作一次dijkstra 没做一次,筛选出最短的路径,而题中(加油站是Gi表示,可以通过substr截取数字部分,并用stoi转换为int型)此时将加油站的下标 + n (因为所有加油站也存在路径)因此作dijkstra算法判定时不止房子的顶点.

 

具体代码实现:

#include<iostream>
#include<string>
#include <iomanip>
/**
此题的不同点就是没有告诉明确的start和end 它的start是所有加油站 end则需要判断出所有的房屋才能明确
思路:多次使用dijkstra算法 
**/
using namespace std;
const int maxsize = 1025;
const int inf = 0x3f3f3f;
int n,m,k,ds;
int edge[maxsize][maxsize],dis[maxsize];
bool visit[maxsize];
//存储gas(加油站)下标,gas到所有房屋最短平均距离,gas到所有房屋的路径种最短
//(相对所有加油站最长的一条)的一条 
int ansid;  
double ansaver=inf,ansmin=-1.0;
void dijkstra(){
	for(int i=n+1;i<=n+m;i++){
		fill(dis,dis+maxsize,inf);
		fill(visit,visit+maxsize,false);
		int index = i;
		//dismin记录此时gas到所有房屋的最短距离,index记录此时gas的索引,
		// sum记录gas到所有房屋的距离 (sum/n (n为房屋的数量)计算出平均值(sumavg)) 
		double dismin=inf,sum=0.0,sumavg=0.0; 
		dis[i]=0;
		//开始判断第i个加油站到各个顶点的距离 
		for(int i = 1;i <= n+m; i++){
			int min = inf,u = -1;
			for(int j = 1;j <= n+m;j++){
				if(dis[j] < min && visit[j] == false){
					min=dis[j];
					u=j;
				}
			}
			visit[u]=true;
//			cout<<"u:"<<u<<" dis[u]:"<<dis[u]<<endl; 测试dijkstra 
			if(u==-1) break; //这里不要写为返回了 因为要判断多条路径 
			for(int k=1;k<=n+m;k++){
				if(visit[k]==false && edge[u][k]!=inf){
					if(dis[k]>dis[u]+edge[u][k]){
						dis[k]=dis[u]+edge[u][k];
					}
				}
			}
		}
		//
		for(int i=1;i<=n;i++){
			if(dis[i]>ds){
				dismin=-1;
				break;
			}
			if(dis[i]<dismin){
				dismin=dis[i];
			}
			sum+=dis[i];
		}
		if(dismin==-1) continue;
		sumavg=sum/n;
		if(dismin>ansmin){ //此时的gas到房屋的最短距离大于之前gas到房屋的距离 
			ansmin=dismin;//更新最短距离 
			ansid=index;//记录此时gas的索引
			ansaver=sumavg;//更新gas到所有房屋距离的平均值 
		}else if(dismin==ansmin && sumavg < ansaver){ //此时距离相等,且到所有房屋的平均值小于之前的平均值 
			ansid=index;//记录此时gas的索引
			ansaver=sumavg;		//更新gas到所有房屋距离的平均值 	
		}
                //至于id更小的情况 不需要判断了,gas的索引就是从小到大判断,min值第一个存放的是
                //索引更小的值
	}
	
} 

int main(){
	ios::sync_with_stdio(false);
	cin>>n>>m>>k>>ds;
	fill(edge[0],edge[0]+maxsize*maxsize,inf);
//	fill(dis,dis+maxsize,inf);
	for(int i=0;i<k;i++){
		int cost,from,to;
		string gas,house;
		cin>>gas>>house>>cost;
		if(gas[0]=='G'){
			gas = gas.substr(1); //返回的是substr(I)从下标为i的字符开始截取 返回string类型字符串 
			from=n+stoi(gas);
		}else{
			from=stoi(gas);
		}
		if(house[0]=='G'){
			house=house.substr(1);
			to=n+stoi(house); 
		}else{
			to=stoi(house);
		}
		edge[from][to]=edge[to][from]=min(edge[from][to],cost);		
	}
	dijkstra();
	
	if(ansmin==-1)
		cout<<"No Solution";
	else{
		cout<<"G"<<ansid-n<<endl<<setiosflags(ios::fixed)<<setprecision(1)<<ansmin<<" "<<ansaver;
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值