PAT 1018 Public Bike Management (30 分)
1018 Public Bike Management (30 分)
There is a public bike service in Hangzhou City which provides great convenience to the tourists from all over the world. One may rent a bike at any station and return it to any other stations in the city.
The Public Bike Management Center (PBMC) keeps monitoring the real-time capacity of all the stations. A station is said to be in perfect condition if it is exactly half-full. If a station is full or empty, PBMC will collect or send bikes to adjust the condition of that station to perfect. And more, all the stations on the way will be adjusted as well.
When a problem station is reported, PBMC will always choose the shortest path to reach that station. If there are more than one shortest path, the one that requires the least number of bikes sent from PBMC will be chosen.
解析
很紮實的30分題。圖應用題。
這題的要求是你從PBMT出發:沿著最短路徑開始排程自行車。遇上一個station:如果這裡自行車有多的:則拿走一些。如果自行車少了:就先從手頭看看有沒有之前在其他station收的自行車。如果沒有:就要sent了。
這個行為是要一個station到另一個station:是不滿足dijkstra區域性最優解的。所以用dijkstra只能算最短路徑。
而且不能說前面station的自行車不夠:用後面的station的自行車補給。這是不對的。
這題有三個標尺:第一個是最短路徑,可以用Dijkstra演算法解決。
第二個是最少sent,第三個是最少take back。當時我一想:sent和take back不是矛盾的嗎。其實我是忽略了不能說前面station的自行車不夠:用後面的station的自行車補給。
所以:在所有最短路徑中:看誰的sent是最少的。如果一樣:就挑誰的take back最小。DFS
Code:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<utility>
using namespace std;
const int INF = 0x3fffffff;
struct Node {
int v,len;
Node() = default;
Node(int _v,int _len):v(_v),len(_len){}
};
int Cmax;
vector<vector<Node>> G;
vector<int> C;
vector<vector<int>> pre;
void Dijkstra(int s, vector<int>& d) {
vector<bool> vis(G.size(), false);
pre.resize(G.size());
d.resize(G.size(), INF);
d[s] = 0;
for (int i = 0; i < G.size(); i++) {
int u = -1, min = INF;
for (int j = 0; j < G.size(); j++) {
if (vis[j] == false && min > d[j]) {
min = d[j];
u = j;
}
}
vis[u] = true;
for (auto x : G[u]) {
int v = x.v;
if (vis[v] == false) {
if (d[v] > d[u] + x.len) {
d[v] = d[u] + x.len;
pre[v].clear();
pre[v].push_back(u);
}
else if (d[v] == d[u] + x.len) {
pre[v].push_back(u);
}
}
}
}
}
vector<int> temppath, path;
int minneed = INF,minremain = INF;
void DFS(int s,int v) {
if (s == v) {
temppath.push_back(s);
int remain = 0,need=0;
for (int i = temppath.size() - 2; i >= 0; i--) {
int last = C[temppath[i]] - Cmax / 2;
if (last > 0) { // 有多的
remain += last;
}
else { //缺
if (remain > abs(last))
remain -= abs(last);
else{
need += abs(last) - remain;
remain = 0;
}
}
}
if (minneed > need) {
minneed = need;
minremain = remain;
path = temppath;
}
else if(minneed ==need ) {
if (remain < minremain) {
minremain = remain;
path = temppath;
}
}
temppath.pop_back();
}
temppath.push_back(v);
for (auto x : pre[v])
DFS(s, x);
temppath.pop_back();
}
int main()
{
int N, Sp, M;
scanf("%d %d %d %d", &Cmax, &N, &Sp, &M);
G.resize(N + 1); //0 is PBMC ,1~N is station
C.resize(N + 1);
for (int i = 1; i <= N; i++)
scanf("%d", &C[i]);
int Si, Sj, Tij;
for (int i = 0; i < M; i++) {
scanf("%d %d %d", &Si, &Sj, &Tij);
G[Si].push_back(Node(Sj, Tij));
G[Sj].push_back(Node(Si, Tij));
}
vector<int> d;
Dijkstra(0,d);
DFS(0,Sp);
printf("%d ", minneed);
for (int i = path.size() - 1; i >= 0; i--) {
printf("%d", path[i]);
if (i > 0) printf("->");
}
printf(" %d", minremain);
}