题目链接
思路
①求最短路径,满足最优子结构,即任意一条最短路径中所包含的子路径也是最短路径,用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;
}