原题链接: https://www.patest.cn/contests/pat-a-practise/1018)
选择最短路径比较简单,dijkstra算法即可,但是要考虑send_bikes和back_bikes,注意在去程途中,如果先前的节点中有多余的自行车,可以提供给后面站点,这样从PBMC中带出的自行车就会少一点,但是返程途中不可以再将带回的自行车放置在其他站点中,比如一条路线为6->7->3->6;那么send_bikes =0, back_bikes = 2。
代码思路是dijkstra算法先找出所有的最短路径,然后回溯,选择满足条件的结果,思路还是比较清晰的。PS:这道题目真心是太烦了
#include <iostream> #include <cstdio> #include <vector> #include <string> using namespace std; const int INF = 0x6FFFFFFF; int Cmax, N, Sp, M; int bikes[501]; //每一个节点含有的自行车数量 int graph[501][501]; //图 int dist[501]; vector<int> path[501]; void dijkstra() { int source = 0; int flag[501]; int k; for (size_t i = 0; i <= N; i++) { flag[i] = 0; dist[i] = graph[0][i]; path[i].push_back(0); } flag[source] = 1; dist[source] = 0; for (size_t i = 1; i <= N; i++) { int min = INF; //find the closest point for (size_t j = 1; j <= N; j++) { if (flag[j] == 0 && dist[j] < min) { min = dist[j]; k = j; } } flag[k] = 1; for (size_t j = 1; j <= N; j++) { if (flag[j] == 0) { int tmp = min + graph[k][j]; if (tmp < dist[j]) { dist[j] = tmp; path[j].clear(); path[j].push_back(k); } else if (tmp == dist[j]) { path[j].push_back(k); } } } } } vector<int> one_path, best_path; int min_back_bike = INF, min_send_bike = INF; void dp(int node) { if (node == 0) { int back = 0; int send = 0; for (int i = one_path.size() - 2; i >= 0; i--) { int t = one_path[i]; if (bikes[t] > (Cmax / 2)) back += bikes[t] - Cmax / 2; else if (bikes[t] < (Cmax / 2)) { back += bikes[t] - Cmax / 2; if (back < 0) { send += -back; back = 0; } } } if (send < min_send_bike) { min_send_bike = send; min_back_bike = back; best_path = one_path; } else if (send == min_send_bike && back < min_back_bike) { min_back_bike = back; best_path = one_path; } } else { for (size_t i = 0; i < path[node].size(); i++) { one_path.push_back(path[node][i]); dp(path[node][i]); one_path.pop_back(); } } } int main(void) { cin >> Cmax >> N >> Sp >> M; for (size_t i = 0; i <= N; i++) { for (size_t j = 0; j <= N; j++) { graph[i][j] = INF; } graph[i][i] = 0; } for (size_t i = 1; i <= N; i++) cin >> bikes[i]; for (size_t i = 0; i < M; i++) { int m, n, t; cin >> m >> n >> t ; graph[m][n] = t; graph[n][m] = t; } dijkstra(); one_path.push_back(Sp); dp(Sp); cout << min_send_bike << " " << 0; for (int i = best_path.size() - 2; i >= 0; i--) cout << "->" << best_path[i]; cout << " " << min_back_bike << endl; }