常规的图的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;
}