PTA 1087(dijkstra + dfs)
1087. All Roads Lead to Rome (30)-PAT甲级真题(Dijkstra + DFS)
Indeed there are many different tourist routes from our city to Rome. You are supposed to find your clients the route with the least cost while gaining the most happiness.
Input Specification:
Each input file contains one test case. For each case, the first line contains 2 positive integers N (2<=N<=200), the number of cities, and K, the total number of routes between pairs of cities; followed by the name of the starting city. The next N-1 lines each gives the name of a city and an integer that represents the happiness one can gain from that city, except the starting city. Then K lines follow, each describes a route between two cities in the format “City1 City2 Cost”. Here the name of a city is a string of 3 capital English letters, and the destination is always ROM which represents Rome.
Output Specification:
For each test case, we are supposed to find the route with the least cost. If such a route is not unique, the one with the maximum happiness will be recommended. If such a route is still not unique, then we output the one with the maximum average happiness — it is guaranteed by the judge that such a solution exists and is unique.
ence in the first line of output, you must print 4 numbers: the number of different routes with the least cost, the cost, the happiness, and the average happiness (take the integer part only) of the recommended route. Then in the next line, you are supposed to print the route in the format “City1->City2->…->ROM”.
Sample Input:
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
Sample Output:
3 3 195 97
HZH->PRS->ROM
题目大意: 从一个城市到罗马有很多不同的路线,让你给出一条能花费最小的价钱同时获得最大幸福感的路线,当有不止1条花费最小价钱的路线时,就选择其中获得幸福感最大的路线,如果还不止一条,那就再选择其中平均幸福感最大的路线,保证有且仅有一条
思路:满足最优子结构,dijkstra算法求单源最少价钱问题,在最短路径上不仅存在边权,又存在点权,每个城市的幸福感相当于点权,求最少价钱路线的数量,最少的花费,最优路线的幸福感总和,平均幸福感,分别开对应的数组来记录其结果,用pre数组来记录路线的每个城市的前一个城市节点。
如何存储
储存字符串+数值 (字符串加点权)的数组时用:pair<string, int> arr[205]; arr.first ->string arr.second ->int
可以用unordered_map<string, int> strToIndex;储存pair数组对应的下标,方便后面好寻找
dijkstra算法:
步骤:
- 为路径数组e ,dis赋值为INF后 ,再为e输入对应点之间的路径长度,保证没有赋值的点之间的长度为无限大
- 寻找到起点dis数组中到已经存在路径中的最短路径的点u
- 标记点u为true,表示u已经找到了与c1之间的最短路径
- 以u为中转站,更新未找到最短路径点之间的更短的路径
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
int n, k;
string startcity;
int e[205][205];
int cost[205];
int happiness[205], resavehap[205], citycnt[205], pre[205], loadcnt[205];
bool visited[205];
// 字符串+数值
//arr[1] = ("ROM",100);
// pair<string, int> p;
// map<string, int> m;
// unordered_map<string, int> m1;
pair<string, int> arr[205];
unordered_map<string, int> strToIndex;
void dfs(int k){
if(k == strToIndex[startcity]){
cout << arr[k].first << "->";
return;
}
dfs(pre[k]);
cout << arr[k].first ;
if(k != strToIndex["ROM"]) cout << "->";
return;
}
int main() {
cin >> n >> k >> startcity;
fill(e[0], e[0] + 205 * 205, INF);
fill(cost, cost + 205, INF);
arr[0] = {startcity, 0};
for(int i = 1; i <= n-1; i++) {
string t;
int ha ;
cin >> t >> ha;
arr[i] = {t, ha};
strToIndex[arr[i].first] = i;
}
for(int i = 0; i < k; i++) {
string c1, c2;
int cost;
cin >> c1 >> c2 >> cost;
e[strToIndex[c1]][strToIndex[c2]] = e[strToIndex[c2]][strToIndex[c1]] = cost;
}
cost[0] = 0;
pre[0] = 0;
loadcnt[0] = 1;
for(int i = 0; i < n; i++){
int u = -1, minn = INF;
for(int j = 0; j < n; j++){
if(!visited[j] && minn > cost[j]){
u = j;
minn = cost[j];
}
}
if(u == -1) break;
visited[u] = true;
for(int v = 0; v < n; v++){
if(!visited[v] && e[u][v] != INF){
if(e[u][v] + cost[u] < cost[v]){
cost[v] = e[u][v] + cost[u];
happiness[v] = happiness[u] + arr[v].second;
citycnt[v] = citycnt[u] + 1;
resavehap[v] = happiness[v] / citycnt[v];
pre[v] = u;
loadcnt[v] = loadcnt[u];
} else if(e[u][v] + cost[u] == cost[v]){
int count = citycnt[u] + 1;
int ave = (happiness[u] + arr[v].second) / count;
loadcnt[v] += loadcnt[u];
if(happiness[u] + arr[v].second > happiness[v]){
happiness[v] = happiness[u] + arr[v].second;
citycnt[v] = count;
resavehap[v] = ave;
pre[v] = u;
}else if(happiness[u] + arr[v].second == happiness[v] && ave > resavehap[v]){
citycnt[v] = count;
resavehap[v] = ave;
pre[v] = u;
}
}
}
}
}
// 最小花费路线的数量
cout << loadcnt[strToIndex["ROM"]] << " ";
cout << cost[strToIndex["ROM"]] << " " << happiness[strToIndex["ROM"]] << " " << resavehap[strToIndex["ROM"]] ;
cout << endl;
dfs(strToIndex["ROM"]);
return 0;
}
341

被折叠的 条评论
为什么被折叠?



