PAT甲级真题1087 条条大路通罗马

从我们的城市到达罗马有许多不同的旅游路线。

请你在成本最低的旅游路线之中,找到使得游客幸福感最强的路线。

输入格式
第一行包含两个整数 NN 和 KK,分别表示总城市数量,城市之间道路数量,还包含一个城市名字,表示初始城市。

接下来 N−1N−1 行,每行包含一个城市名和一个整数,表示到达该城市(初始城市除外)可以获得的幸福感。

接下来 KK 行,每行包含一个道路的信息,格式为 City1 City2 Cost,表示两个城市之间的道路行走的花费,道路是双向的。

城市都是由三个大写字母构成的字符串。

我们的目的地始终都是罗马 ROM。

输出格式
我们应该找到成本最低的路线。

如果这样的路线不是唯一的,那么选取使人们获得最大幸福感的路线。

如果这样的路线仍然不是唯一的,那么我们选择平均幸福感最大的路线,数据保证这种路线唯一。

平均幸福感 = 总幸福感 / 经过的城市数量(初始城市不算)

第一行输出四个整数,最小成本的路线数量,最小成本,幸福感,平均幸福感(只取整数部分)。

第二行,按照 City1->City2->…->ROM 的格式输出路线。

数据范围
2≤N≤2002≤N≤200,
1≤K≤2501≤K≤250,
每个城市的幸福感范围在 [0,100][0,100],
每条路线最大成本不超过 10001000

输入样例:
6 7 HZH
ROM 100
PKN 40
GDN 55
PRS 95
BLN 80
ROM GDN 1
BLN ROM 1
HZH PKN 1
PRS ROM 2
BLN HZH 2
PKN GDN 1
HZH PRS 1
输出样例:
3 3 195 97
HZH->PRS->ROM
#include<bits/stdc++.h>
using namespace std;
const int N=250;
int g[N][N],w[N];
int n,m;
int dist[N],weight[N],cnt[N],sum[N],pre[N];//sum记录点数 平均幸福感最大点数最小路线
bool st[N];
unordered_map<string, int>mp1;
unordered_map<int, string>mp2;
void dijiskstra(){
	memset(dist,0x3f,sizeof dist);
	dist[1]=0;
	sum[1]=0;//初始城市不算 
	cnt[1]=1;
	for(int i=0;i<n;i++){ //循环n次 
		int t=-1;
		for(int j=1;j<=n;j++){
			if(!st[j]&&(t==-1||dist[j]<dist[t]))
			 t=j;
		}
		if(t==-1)break;
		st[t]=true;
		for(int v=1;v<=n;v++){
			if(dist[t]+g[t][v]<dist[v]){
				dist[v]=dist[t]+g[t][v];
				pre[v]=t;
				cnt[v]=cnt[t];
				weight[v]=weight[t]+w[v];
				sum[v]=sum[t]+1;
			}
			else if(dist[t]+g[t][v]==dist[v]){
			    	cnt[v]+=cnt[t]; //无论如何都得加 
				if(weight[t]+w[v]>weight[v]){  //幸福感 
				  weight[v]=weight[t]+w[v];
				  pre[v]=t;
				  sum[v]=sum[t]+1;
				} 
				else if(weight[t]+w[v]==weight[v])  {
					if(sum[t]+1<sum[v]){  //平均幸福感 
					pre[v]=t;
					sum[v]=sum[t]+1;
				}
			}
		}
	}
  }
}
int main(){
	cin>>n>>m;
	string s;
	cin>>s;
	mp1[s]=1;
	mp2[1]=s;
	for(int i=2;i<=n;i++){
		 string b;
		 int c;
		 cin>>b>>c;
		 mp1[b]=i;
		 mp2[i]=b;
		 w[i]=c;//点权 
	} 
	memset(g,0x3f,sizeof g);//记得初始化 
	for(int i=0;i<m;i++){
		string a,b;
		int c;
		cin>>a>>b>>c;
		int t1=mp1[a];
		int t2=mp1[b];
		g[t1][t2]=g[t2][t1]=min(c,g[t1][t2]);	
	} 
	dijiskstra();
    int T=mp1["ROM"];
    cout<<cnt[T]<<' '<<dist[T]<<' '<<weight[T]<<' '
    <<weight[T]/sum[T]<<endl;
    cout<<mp2[1];
    vector<int> v;
    for(int i=T;i!=1;i=pre[i]){
    	v.push_back(i);
    }
    for(int i=v.size()-1;i>=0;i--){
    	cout<<"->"<<mp2[v[i]];
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小王子y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值