PAT(Advanced)甲级1087 All Roads Lead to Rome
相关内容
PAT(Advanced)1003 Emergency (Dijkstra最短路) (邻接矩阵)C++实现
DijkstraSSSP(单源最短路径求解)(迪克斯特拉算法堆优化)(Java实现)(邻接矩阵)(优先级队列)(堆优化)
Dijkstra最短路(迪克斯特拉算法)(C++实现)(邻接矩阵)
题目链接
题目大意
给定出发城市,存在的路线及路线长度,目的地为罗马,求解到达罗马的最短路径
,除了出发城市外,每个城市有对应的幸福值,在求得最短路径的情况下,若最短路径不唯一则求解累积幸福值最高的路线
,若幸福值最高的最短路径仍然不唯一,则求解平均幸福值最高的路线,平均幸福值为路线总幸福值与除了出发城市外的城市数量的比值
,输出为最小代价路径数量
,最短路径代价
,最短路径中的最大幸福值
,具有最大幸福值的最短路径最高平均幸福值
以及具有最大幸福值和最高平均幸福值的最短路径从出发城市到目的地罗马的路线序列
算法思路
求解单源最短路,采用Dijkstra最短路径算法
设置优先级队列优先级,其中d距离优先级最高,幸福值次之,平均幸福值最小,距离越小优先级越高,距离相同情况下,幸福值越大优先级越高,距离和幸福值相同情况下,平均幸福值越高优先级越高,即路径经过城市数越少优先级越高
struct Node{
int num;
int dist;
int happiness;
int passByCity;
bool operator < (const Node& x) const{
// return dist == x.dist ? happiness < x.happiness : dist > x.dist;
return dist == x.dist ? (happiness == x.happiness ? passByCity > x.passByCity : happiness < x.happiness ) : dist > x.dist;
}
};
更新dist数组及相应值
if (dist[i] >= dist[top] + matrix[top][i]) {
if (dist[i] == dist[top] + matrix[top][i]) {
// 若dist数组对应值相等
// 更新路线数量
// 由于长度相等,则在顶点i原来的路线数量基础上增加top为前驱的路线数量
routes[i] += routes[top];
// 考虑路线幸福值总数和平均幸福值情况...
if (happinessValue[i] < happinessValue[top] + happiness[i]) {
happinessValue[i] = happinessValue[top] + happiness[i];
dijkstraSSSP[i] = top;
passByCityNumber[i] = passByCityNumber[top] + 1;
pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});
} else if (happinessValue[i] == happinessValue[top] + happiness[i]) {
if (passByCityNumber[i] > passByCityNumber[top] + 1) {
dijkstraSSSP[i] = top;
passByCityNumber[i] = passByCityNumber[top] + 1;
pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});
}
}
} else {
// 若存在更短dist数组,则更新路线值,城市幸福值和路径城市数量
routes[i] = routes[top];//更新路线数量
dist[i] = dist[top] + matrix[top][i];//更新dist数组对应值
happinessValue[i] = happinessValue[top] + happiness[i];//更新幸福值
dijkstraSSSP[i] = top;//更新最短路径
passByCityNumber[i] = passByCityNumber[top] + 1;//更新路径城市数量
pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});//将新的顶点及相关信息入堆
}
}
考虑路线幸福值总数和平均幸福值情况
if (happinessValue[i] < happinessValue[top] + happiness[i]) {
// 若存在更高幸福值的最短路径
happinessValue[i] = happinessValue[top] + happiness[i];// 更新最短路径
dijkstraSSSP[i] = top;// 更新最短路径回溯数组
passByCityNumber[i] = passByCityNumber[top] + 1;// 更新最短路径路径城市数量
pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});// 将新顶点及相关信息入堆
} else if (happinessValue[i] == happinessValue[top] + happiness[i]) {
// 若幸福值相等
// 考虑城市最大平均幸福值情况...
if (passByCityNumber[i] > passByCityNumber[top] + 1) {
dijkstraSSSP[i] = top;
passByCityNumber[i] = passByCityNumber[top] + 1;
pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});
}
}
考虑城市最大平均幸福值情况
if (passByCityNumber[i] > passByCityNumber[top] + 1) {
// 若存在更大的城市平均幸福值
dijkstraSSSP[i] = top;// 更新最短路径回溯数组
passByCityNumber[i] = passByCityNumber[top] + 1;// 更新最短路径路径城市数量
pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});// 将新顶点及相关信息入堆
}
首先考虑最短路径的情况,在存在多条最短路径的情况下,选取幸福值最高的路线,在存在多条幸福值最高且相同的最短路径的情况下,选取最高城市平均值的最短路径
AC代码
/*
author : eclipse
email : [email protected]
time : Wed Jun 24 23:40:49 2020
*/
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x10000000;
const int MAX_SIZE = 256;
int vextexNumber;
int routeNumber = 0;
vector<int> routes;
vector<int> happiness;
vector<int> happinessValue;
vector<int> dijkstraSSSP;
vector<int> dist;
vector<vector<int> > matrix;
vector<int> passByCityNumber;
map<string, int> cityOrder;
map<int, string> orderCity;
struct Node{
int num;
int dist;
int happiness;
int passByCity;
bool operator < (const Node& x) const{
return dist == x.dist ? (happiness == x.happiness ? passByCity > x.passByCity : happiness < x.happiness ) : dist > x.dist;
}
};
void dijkstra() {
vector<bool> tag;
tag.resize(vextexNumber);
for (int i = 0; i < vextexNumber; i++) {
dist[i] = INF;
dijkstraSSSP[i] = 0;
tag[i] = false;
}
priority_queue<Node> pq;
pq.push((Node) {0, 0, 0, 0});
dist[0] = 0;
dijkstraSSSP[0] = 0;
while (!pq.empty()) {
int top = pq.top().num;
pq.pop();
if (tag[top]) {
continue;
}
tag[top] = true;
for (int i = 0; i < vextexNumber; i++) {
if (dist[i] >= dist[top] + matrix[top][i]) {
if (dist[i] == dist[top] + matrix[top][i]) {
routes[i] += routes[top];
if (happinessValue[i] < happinessValue[top] + happiness[i]) {
happinessValue[i] = happinessValue[top] + happiness[i];
dijkstraSSSP[i] = top;
passByCityNumber[i] = passByCityNumber[top] + 1;
pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});
} else if (happinessValue[i] == happinessValue[top] + happiness[i]) {
if (passByCityNumber[i] > passByCityNumber[top] + 1) {
dijkstraSSSP[i] = top;
passByCityNumber[i] = passByCityNumber[top] + 1;
pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});
}
}
} else {
routes[i] = routes[top];
dist[i] = dist[top] + matrix[top][i];
happinessValue[i] = happinessValue[top] + happiness[i];
dijkstraSSSP[i] = top;
passByCityNumber[i] = passByCityNumber[top] + 1;
pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});
}
}
}
}
}
void print(int destination, map<int, string> orderCity) {
stack<int> s;
int current = destination;
while (current) {
s.push(current);
current = dijkstraSSSP[current];
}
printf("%d %d %d %d\n", routes[destination], dist[destination], happinessValue[destination], happinessValue[destination] / passByCityNumber[destination]);
cout << orderCity[0];
while (!s.empty()) {
cout << "->" << orderCity[s.top()];
s.pop();
}
}
int main(int argc, char const *argv[]) {
int N, M;
scanf("%d%d", &N, &M);
vextexNumber = N;
string start;
routes.resize(vextexNumber);
happinessValue.resize(vextexNumber);
dijkstraSSSP.resize(vextexNumber);
dist.resize(vextexNumber);
passByCityNumber.resize(vextexNumber);
happiness.resize(vextexNumber);
cin >> start;
orderCity[0] = start;
cityOrder[start] = 0;
happiness[0] = 0;
for (int i = 1; i < vextexNumber; i++) {
string city;
int value;
cin >> city >> value;
happiness[i] = value;
orderCity[i] = city;
cityOrder[city] = i;
}
matrix.resize(vextexNumber);
for (int i = 0; i < vextexNumber; i++) {
happinessValue[i] = 0;
passByCityNumber[i] = 0;
routes[i] = 0;
matrix[i].resize(vextexNumber);
routes[i] = 1;
for (int j = 0; j < vextexNumber; j++) {
matrix[i][j] = INF;
}
}
for (int i = 0; i < M; i++) {
string u, v;
int weight;
cin >> u >> v >> weight;
matrix[cityOrder[u]][cityOrder[v]] = weight;
matrix[cityOrder[v]][cityOrder[u]] = weight;
}
dijkstra();
print(cityOrder["ROM"], orderCity);
return 0;
}
样例输入
6 7 HZH
ROM 100
PKN 40
GDN 55
PRS 95
BLN 80
ROM GDN 1
BLN ROM 1
HZH PKN 1
PRS ROM 2
BLN HZH 2
PKN GDN 1
HZH PRS 1
样例输出
3 3 195 97
HZH->PRS->ROM
鸣谢
最后
- 本题考虑的情况有些多,需要注意的是要考虑路线数量、经过城市数和幸福值在更新时需要继承其直接前驱顶点的状态,若忽略则可能无法通过某些测试点
- 本题空间消耗比较大,若在类中写可能会导致段错误,上述代码没有采用递归的方式,则段错误为数组越界的错误,故在数组较大的情况下尽量使用全局变量,使用内存堆区
- 由于博主水平有限,不免有疏漏之处,欢迎读者随时批评指正,以免造成不必要的误解!