1087 All Roads Lead to Rome (30point(s))(Dijkstra)

题目链接

思路

①求最短路径,满足最优子结构,即任意一条最短路径中所包含的子路径也是最短路径,用dijkstra,来个贪心就够了
②继续分析,求最短路径的条数,附属于①的一个问题,可同时算
③继续分析,求最大幸福指数,先判断是否满足最优子结构,结果:满足。取出幸福感最大的最短路径,你会发现,其中的某一部分的幸福指数也是最大的,如果还可以再少,原假设可就不成立了
④继续分析,求平均幸福指数最大的最短路径,先判断是否满足最优子结构,结果:满足。取出总幸福指数相同,但平均幸福指数最大的最短路径,你会发现,其中的某一部分路径,其平均幸福指数也是最大的,如果还可以再少,原假设可就不成立了
⑤继续分析,求平均幸福感最大的最短路径的结点个数,附属于①和④的一个问题,可同时算
⑦庆幸,一遍dijkstra下来就可以解决所有问题,需要耐心的一道题。
⑧如果需求中有一个不满足最优子结构,那么对最短路径树来一遍深度搜索

代码

using namespace std;
#include<bits/stdc++.h>
int N, K,happy[200],cnt=1,happyIndex,lenth;
int graph[200][200],dis[200],visited[200],num[200],joy[200],ave[200],nodes[200];
vector<int>pre,path;
string start,aim="ROM",name,origin,dest;
map<string, int>para;
map<int, string>oppo;
void dijkstra() {
	for (int i = 0; i < N-1 ; i++) {
		int max = 0x3f3f3f3f, index = -1;
		for (int j = 0; j < N ; j++) {
			if (dis[j] < max && !visited[j]) {
				max = dis[j];
				index = j;
			}
		}
		if (index == -1)break;
		visited[index] = 1;
		for (int k = 0; k < N ; k++) {
			if (!visited[k]) {
				if (dis[index] + graph[index][k] < dis[k]) {
					dis[k] = dis[index] + graph[index][k];
					num[k] = num[index];
					joy[k] = joy[index] + happy[k];
					pre[k] = index;
					nodes[k] = nodes[index] + 1;
					ave[k] = joy[k] / nodes[k];
				}
				else if (dis[index] + graph[index][k] == dis[k]) {
					if (i != 0) {
						num[k] += num[index];
						if (joy[index] + happy[k] > joy[k]) {
							joy[k] = joy[index] + happy[k];
							nodes[k] = nodes[index] + 1;
							pre[k] = index;
							ave[k] = joy[k] / nodes[k];
						}
						else if (joy[index] + happy[k] == joy[k]) {
							if ((joy[index] + happy[k]) / (nodes[index] + 1) > (joy[k] / nodes[k])) {
								nodes[k] = nodes[index] + 1;
								pre[k] = index;
								ave[k] = joy[k] / nodes[k];
							}
						}
					}
				}
			}
		}
	}
}
int main() {
	//---------------------初始化部分--------------------------------
	//尽量把初始化和dijkstra函数完全区分,以防遗漏
	//int N,K如题目中所示
	//string start :起点
	//string aim:终点(ROM)
	//string name:暂时的一个变量:城市名称
	//string origin:顶点1
	//string dest:顶点2
	//int lenth:顶点1和顶点2的距离
	//map<string,int> para:某个城市字符串所对应的id
	//int cnt:用来分配id
	//map<int,string> oppo:某个id所对应的城市字符串
	//int happy[]:某个城市的幸福指数
	//int graph[][]:存图(费用)
	//int dis[]:起点到某个点的最少费用
	//int visited[]:某个点是否已经被用来收缩其他顶点
	//int num[]:起点到某个点的最短路径上条数
	//int nodes[]:起点到某个点的最短路径上顶点的个数(不包括起点)
	//int joy[]:起点到某个点的最短路径的总的幸福感
	//int ave[]:起点到某个点的最短路径的平均幸福感
	cin >> N >> K >> start;
	memset(graph, 0x3f, sizeof graph);
	memset(dis, 0x3f, sizeof dis);
	dis[0] = 0;
	para[start] = 0;
	oppo[0] = start;
	happy[0] = 0;
	num[0] = 1;
	pre.resize(N);
	pre[0] = -1;
	for (int i = 0; i < N - 1; i++) {
		cin >> name >> happyIndex;
		para[name] = cnt++;
		oppo[cnt - 1] = name;
		happy[para[name]] = happyIndex;
	}
	for (int i = 0; i < K; i++) {
		cin >> origin >> dest >> lenth;
		graph[para[origin]][para[dest]] = graph[para[dest]][para[origin]] = lenth;
	}
	//-----------------------------执行dijkstra---------------------
	dijkstra();
	//-----------------------------结果处理-------------------------
	//相比于之前写的1072\1030题,可直接用一个for循环将正常路径处理出来
	int t = para[aim];
	cout << num[t] << " " << dis[t] << " " << joy[t] << " " << ave[t] << endl;
	for (int i = t; i !=-1; i = pre[i])path.push_back(i);
	for (int i = path.size() - 1; i >= 0;i--) {
		cout << oppo[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、付费专栏及课程。

余额充值