1087 All Roads Lead to Rome (30 分)

本文介绍了一种结合最短路径与最大幸福值的算法实现,通过Dijkstra算法寻找两点间的最短路径,并在此基础上计算路径上的最大幸福值。文章详细展示了如何使用哈希映射将城市名转换为整数索引,以便于处理和存储,同时提供了完整的代码实现,包括Dijkstra算法的实现和深度优先搜索(DFS)用于寻找最优路径。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=1e2+5;
const int INF = 0x3fffffff;
int m,n,x; 
int k=0;
int h[maxn]={0};
vector<int> pre[maxn];
vector<int> path, tempPath;
int G[maxn][maxn];
int opt = -1, num = 0;
double ave=0;
bool vis[maxn]={false};
int d[maxn];
void Dijkstra() {
	fill(d, d+maxn, INF);
	d[0] = 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){
				MIN = d[j];
				u = j;
			}
		}
		if(u == -1) return;
		vis[u] = true; //狗日的bug害我调半天 
		for(int v = 0; v < n; v++){
			if(vis[v]==false && G[u][v] != INF){
				if(d[v] > d[u] + G[u][v]){
					d[v] = d[u] + G[u][v];
					pre[v].clear();
				}
				if(d[v] == d[u] + G[u][v]){
					pre[v].push_back(u);
				}
			}
		}
	}
}
void DFS(int v){
	if(v == 0){
		tempPath.push_back(v);
		num++;
		int value = 0;
		for(int i = 0; i < tempPath.size(); i++){
			int id = tempPath[i];
			value += h[id];
		}
		double tmpave = value*1.0/(tempPath.size()-1);
		if(value > opt){
			path = tempPath;
			opt = value;
			ave = tmpave;
		}else if(value == opt){
			if(tmpave > ave){
				path = tempPath;
				ave = tmpave;
			}
		}
		tempPath.pop_back();
		return;
	}
	tempPath.push_back(v);
	for(int u = 0; u < pre[v].size(); u++){
		int w = pre[v][u];
		DFS(w);
	}
	tempPath.pop_back();
}
int main(){
	string s,ss;
	unordered_map<string, int> SI;
	unordered_map<int, string> IS;
	cin>>n>>m>>s;
	int index = 0;
	SI[s] = index;
	IS[index] = s;
	index++;
	h[0] = 0;
	for(int i = 0; i < n - 1; i++) {
		cin >> s >> x;
		SI[s] = index;
		IS[index] = s;
		h[index] = x;
		index++;
	}
	fill(G[0], G[0]+maxn*maxn, INF);
	for(int i = 0; i < m; i++) {
		cin>>s>>ss>>x;
		int u = SI[s];
		int v = SI[ss];
		G[u][v] = x;
		G[v][u] = x;
	}
	int r = SI["ROM"];
	
	Dijkstra();
	DFS(r);
	cout<<num<<" "<<d[r]<<" "<<opt<<" ";
	printf("%d\n",(int)ave);
	for(int i=path.size()-1;i>=0;i--){
		int t = path[i];
		cout<<IS[t];
		if(i != 0) cout<<"->";
		else cout<<endl;
} 
	return 0;
}

版本2

主要是考虑怎么把字符串转换为数字
直接用两个map相互查找就行了
这种题就是见过了就知道怎么做
没什么技术含量

#include<iostream>
#include<cstdio>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
int n,k;
string st;
const int maxn=210;
const int INF=1e9+5;
map<string,int> City2Index;
map<int,string> Index2City;
int weight[maxn]; 
int G[maxn][maxn]; //耗时 
int d[maxn]; //耗时最短
bool vis[maxn]={false}; 
int num=0; //最短路径有多少条 
vector<int> path,tempPath;
vector<int> pre[maxn];
void Dijkstra(int s){
	fill(d,d+maxn,INF);
	d[s]=0;
	for(int i=0;i<n;i++){ //n个顶点 
		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(G[u][v] + d[u] < d[v]){
					d[v]=G[u][v] + d[u];
					pre[v].clear();
					pre[v].push_back(u); //把u设为前驱节点 
				}else if(G[u][v] + d[u] == d[v]){
					pre[v].push_back(u); //直接加在v的后面,表示还有另一个前驱 
				} 
			}
		}
	}
	
}
int maxhappy=0;
double avehappy;
void DFS(int v) {
	if(v==0){
		tempPath.push_back(v);
		num++; 
		weight[0]=0;
		int tempmax=0;
		double tempave=0;
		for(int i=tempPath.size()-1;i>=0;i--){ //从0开始到终点 
			int id=tempPath[i];
			tempmax+=weight[id];
		}
		tempave= tempmax*1.0/(tempPath.size()-1);
		if(tempmax > maxhappy){
			maxhappy = tempmax;
			avehappy = tempave;
			path = tempPath;
		}else if(tempmax == maxhappy && tempave > avehappy){
			avehappy = tempave;
			path = tempPath;
		}
		tempPath.pop_back();
		return;	
	}
	tempPath.push_back(v);
	for(int j=0;j<pre[v].size();j++){
		DFS(pre[v][j]);
	}
	tempPath.pop_back();
}

int main(){
	cin>>n>>k>>st;
	string st1,st2,str;
	City2Index[st]=0;  //把城市转换为索引 
	Index2City[0]=st;  //把索引转换为城市 
	fill(G[0],G[0]+maxn*maxn,INF);
	for(int i=1;i<n;i++){   //点权幸福值  此处把所有城市都存下来了 
		cin>>str>>weight[i];
		City2Index[str]=i;
		Index2City[i]=str;
	}
	int cost;
	for(int i=0;i<k;i++){ //边权距离 
		cin>>st1>>st2;
		int c1=City2Index[st1],c2=City2Index[st2];  //先找出城市对应的索引 
		cin>>cost;
		G[c1][c2]=cost;
		G[c2][c1]=cost;  //无向图 
	}
	
	
	Dijkstra(0);
	int rom=City2Index["ROM"]; //终点 
	DFS(rom);
	printf("%d %d %d %d\n",num,d[rom],maxhappy,int(avehappy));
	for(int i=path.size()-1;i>=0;i--){
		cout<<Index2City[path[i]];
		if(i>0) cout<<"->";
	}
	cout<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值