A1072 Gas Station (30分)

 常规的图的Dijkstra求最短路径的方式但是需要对题目有写理解以及稍微处理一下数据,注意一点细节。。。

pat不能速成。。况且基础我还不好。刷的时候还是有点难受的。。硬学

关于strToNum的方法也很多细节都写错了。。比如s[i]-‘0’(没有转成字符串),判断s[0]=‘G’的时候写成了s[1]

所以可以看到有很多的测试输出。。。我早晚死在自己造的坑上

计算平均值两种方法均可:直接计算。累加后/n计算都行

#include<cstdio>
#include<stdlib.h>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
using namespace std;
//A1072
const int maxn=1020;
const int INF=1e9;
int n,posNum,roads,dmax;
int graph[maxn][maxn];
bool visit[maxn]={false};
int d[maxn];

int strToNum(string s){
	int len=s.length();
	int result=0;
	for(int i=0;i<len;i++){
//		cout<<"s[i]"<<s[i]<<" ";
		if(s[i]!='G'){
			result=result*10+(s[i]-'0');
		}
	}
//	printf("\n");
	if(s[0]=='G'){
//		cout<<"G"<<n+result<<endl;	
		return n+result;
		
	}else {
//		cout<<"resident"<<result<<endl;
		return result;
		
	}
}
void findMin(int start){ //计算从start到每个居民点的最短距离
	//初始化d
	fill(d,d+maxn,INF);
	d[start]=0;
	
	for(int i=1;i<=n+posNum;i++){
		//找到当前未访问节点中的最小值:加油站也可以作为中间节点更新最短路径
		int pos=-1,min=INF;
		for(int j=1;j<=n+posNum;j++){
			if(visit[j]==false&&d[j]<min){
				min=d[j];
				pos=j;
			}
		} 
		if(pos==-1)return;
		visit[pos]=true;
		//更新最短路径:只需要更新从加油站到居民楼的 
		for(int j=1;j<=n+posNum;j++){//注意也得更新加油站的最短路径 
			if(visit[j]==false && graph[pos][j]!=INF){
				//进行最短路的替换 
				if(d[j]>d[pos]+graph[pos][j]){
					d[j]=d[pos]+graph[pos][j];
				} 
			}
		} 
	}
	
}
int main()
{
cin>>n>>posNum>>roads>>dmax;

string a,b;
int value;
fill(graph[0],graph[0]+maxn*maxn,INF);
for(int i=0;i<roads;i++){
	cin>>a>>b>>value;
	int pos1=strToNum(a);
	int pos2=strToNum(b);
	graph[pos1][pos2]=value;
	graph[pos2][pos1]=value;
}	
double maxTopeople=-1;//存放距离最近的居民楼的最长的路径
double minAverage=INF;
int count=0;//累计不符合加油站需求的个数
int findG=0;//存储最终的加油站的下标 
for(int i=n+1;i<=n+posNum;i++){
	//加油站的下标范围
	memset(visit,false,sizeof(visit)); 
	findMin(i);
	int sum=0;
	int min=INF,flag=1;
	double average=0;
	for(int j=1;j<=n;j++){
		if(d[j]>dmax){
//			cout<<i<<":d["<<j<<"]:"<<d[j]<<endl;
			flag=0;//说明不符合条件 
			count++;
			break;
		}
	//	sum+=d[j];//累计距离
		average+=(1.0*d[j])/n;
		if(d[j]<min){//找到最短的距离
			min=d[j];
		} 
	}
	if(flag==0)continue;//不需要计算这轮
//	double average=(1.0*sum)/n;//除以居民楼个数计算平均距离
	//进行最优值的替换
	if(min>maxTopeople){
		maxTopeople=min;//找到距离加油站最近的居民楼的距离最长的一个
		findG=i;//记录该最优解的加油站下标 
		minAverage=average;
//		cout<<maxTopeople<<endl;
		//cout<<"min"<<maxTopeople<<"Average"<<minAverage<<endl;
	}else if(min==maxTopeople){
		//发生最优解相同的情况
		//进行最小平均值的比较
		 if(average<minAverage){
		 	minAverage=average;
		 	findG=i;
		 }
	}
}
if(count==posNum){
printf("No Solution");//说明都是不符合标准的 
return 0;
}else {

	printf("G%d\n",findG-n); 
//	cout<<maxTopeople<<endl;
	printf("%.1f %.1f",maxTopeople,minAverage);//貌似是四舍五入(按照case1的数据是3.25但写成3.3;但是不四舍五入处理也是AC的) 
}
return 0;
	}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值