• 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
    ", 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;
    }
    
    作者:睿晞
    身处这个阶段的时候,一定要好好珍惜,这是我们唯一能做的,求学,钻研,为人,处事,交友……无一不是如此。
    劝君莫惜金缕衣,劝君惜取少年时。花开堪折直须折,莫待无花空折枝。
    曾有一个业界大牛说过这样一段话,送给大家:   “华人在计算机视觉领域的研究水平越来越高,这是非常振奋人心的事。我们中国错过了工业革命,错过了电气革命,信息革命也只是跟随状态。但人工智能的革命,我们跟世界上的领先国家是并肩往前跑的。能身处这个时代浪潮之中,做一番伟大的事业,经常激动的夜不能寐。”
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    no space left on device
    功能测试用例
    数据库命令
    移动APP测试用例设计实践经验(转载)
    15个常用sql命令
    将Windows文件夹挂载到Linux上
    英语学习方法
    三种特质 做领导
    扬州之行 第一天
    list、dict、str虽然是Iterable,却不是Iterator
  • 原文地址:https://www.cnblogs.com/tsruixi/p/12431315.html
Copyright © 2020-2023  润新知