A1087 All Roads Lead to Rome (30分)

一、技术总结

  1. 首先对于题意的理解,N个城市,M条无向边,现在给定某城市作为初始城市,然后一个城市作为终点城市,每条边都需要花费路费,同时每个城市具有幸福值,如果路费最少的有多条,就选择幸福值总和最高的一条,如果任然不唯一,就是选择平均幸福值最高的路径。
  2. 还有一点需要解决的问题是,城市代号全为字符串,也就意味着需要使用map,在int和string之间进行转换。
  3. 同时,这里提出了一个关于平均点权该如何记录和递归的问题,平均点权等于路径上的点权之和除以路径上顶点的数目。
  4. 推荐使用Djikstra+DFS,如下代码所示
  5. 题中初始起点的点权没有给出,因此计算平均点权是不算初始起点的。

二、参考代码

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 210;
const int INF = 0x3fffffff;
bool vis[MAXN] = {false};
int G[MAXN][MAXN], d[MAXN];
int weight[MAXN], w[MAXN];
int n ,m ,st;//n是顶点,m是边数,st是起点的编号
int numPath = 0, maxW = 0; //numPath是最短路径的条数,maxW是最短路径中的最大点权之和
double maxAvg = 0;//最大平均点权 
vector<int> pre[MAXN];//前驱 
vector<int> tempPath, path;//临时路径 
map<string, int> cityToIndex;
map<int, string> indexToCity;

void Djikstra(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, c1, c2;
	cin >> n >> m >> start;
	cityToIndex[start] = 0;
	indexToCity[0] = start;
	for(int i = 1; i < n; i++){
		cin >> c1 >> weight[i];
		cityToIndex[c1] = i;
		indexToCity[i] = c1;
	}
	fill(G[0], G[0]+MAXN*MAXN, INF);
	for(int i = 0; i < m; i++){
		cin >> c1 >> c2;
		int num1 = cityToIndex[c1], num2 = cityToIndex[c2];
		cin >> G[num1][num2];
		G[num2][num1] = G[num1][num2];
	}
	Djikstra(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;
}
posted @ 2020-03-06 22:23  睿晞  阅读(125)  评论(0编辑  收藏  举报