[PAT-A 1087]All Roads Lead to Rome

在这里插入图片描述
考察Dijkstra算法

题目大意:
N个城市,M条无向边,需要从某个给定的起始城市出发,前往ROM。
除起始城市,每个城市都有一个幸福值(点权)
给出每条边的花费(边权)
求从起始城市出发,到达城市ROM所需要的最少的花费,并输出最少花费的路径(第一标尺)
如果有多条,选择幸福值最大的那条(第二标尺)
如果还有多条,选择平均幸福值最大的那条(第三标尺)

考虑DFS+Dijkstra方法,标尺情况已经在大意中列出
选择最短路径

numPath++;
		int tempW = 0;
		for (int i = tempPath.size() - 2; i >= 0; i--) {
			int id = tempPath[i];
			tempW += weight[id];
		}
		double tempAvg = 1.0 * tempW / (tempPath.size() - 1);
		if (tempW > maxW) {
			maxW = tempW;
			maxAvg = tempAvg;
			path = tempPath;
		}
		else if (tempW == maxW && tempAvg >= maxAvg) {//点权相同,平均点权更大
			maxAvg = tempAvg;
			path = tempPath;
		}

AC代码:

//1087 All Roads Lead to Rome (30 分)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>'
using namespace std;
const int maxn = 210;
const int inf = 0x3fffffff;
int n, m, st, G[maxn][maxn], weight[maxn];
int d[maxn], numPath = 0, maxW = 0;
double maxAvg = 0;
bool vis[maxn] = { false };
vector<int> path, tempPath, pre[maxn];
map<string, int>cityToIndex;
map<int, string>indexToCity;
void dijkstra(int s) {
	fill(d, d + maxn, inf);
	d[s] = 0;
	for (int i = 0; i < n; i++) {
		int u = -1, MIN = inf;
		for (int j = 0; j < n; j++) {
			if (vis[j] == false && d[j] < MIN) {
				u = j;
				MIN = d[j];
			}
		}
		if (u == -1)return;
		vis[u] = true;
		for (int v = 0; v < n; v++) {
			if (vis[v] == false && G[u][v] != inf) {
				if (d[u] + G[u][v] < d[v]) {
					d[v] = d[u] + G[u][v];
					pre[v].clear();
					pre[v].push_back(u);
				}
				else if (d[u] + G[u][v] == d[v])pre[v].push_back(u);
			}
		}
	}
}
void dfs(int v) {
	if (v == st) {
		tempPath.push_back(v);
		numPath++;
		int tempW = 0;
		for (int i = tempPath.size() - 2; i >= 0; i--) {
			int id = tempPath[i];
			tempW += weight[id];
		}
		double tempAvg = 1.0 * tempW / (tempPath.size() - 1);
		if (tempW > maxW) {
			maxW = tempW;
			maxAvg = tempAvg;
			path = tempPath;
		}
		else if (tempW == maxW && tempAvg >= maxAvg) {
			maxAvg = tempAvg;
			path = tempPath;
		}
		tempPath.pop_back();
		return;
	}
	tempPath.push_back(v);
	for (int i = 0; i < pre[v].size(); i++) {
		dfs(pre[v][i]);
	}
	tempPath.pop_back();
}
int main() {
	string start, city1, city2;
	cin >> n >> m >> start;
	cityToIndex[start] = 0;
	indexToCity[0] = start;
	st = 0;//起点编号为0;
	for (int i = 1; i < n; i++) {
		cin >> city1 >> weight[i];
		cityToIndex[city1] = i;
		indexToCity[i] = city1;
	}
	fill(G[0], G[0] + maxn * maxn, inf);
	for (int i = 0; i < m; i++) {
		cin >> city1 >> city2;
		int c1 = cityToIndex[city1];
		int c2 = cityToIndex[city2];
		cin >> G[c1][c2];
		G[c2][c1] = G[c1][c2];
	}
	dijkstra(0);
	int rom = cityToIndex["ROM"];
	dfs(rom);
	printf("%d %d %d %d\n", numPath, d[rom], maxW, (int)maxAvg);
	for (int i = path.size() - 1; i >= 0; i--) {
		cout << indexToCity[path[i]];
		if (i > 0)cout << "->";
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值