PAT-1018 Public Bike Management(dijkstra + dfs)
1018. Public Bike Management
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.
Figure 1
Figure 1 illustrates an example. The stations are represented by vertices and the roads correspond to the edges. The number on an edge is the time taken to reach one end station from another. The number written inside a vertex S
is the current number of bikes stored at S. Given that the maximum capacity of each station is 10. To solve the problem at S3, we have 2 different shortest paths:
1. PBMC -> S1 -> S3. In this case, 4 bikes must be sent from PBMC, because we can collect 1 bike from S1 and then take 5 bikes to
S3, so that both stations will be in perfect conditions.
2. PBMC -> S2 -> S3. This path requires the same time as path 1, but only 3 bikes sent from PBMC and hence is the one that will be chosen.
Input Specification:
Each input file contains one test case. For each case, the first line contains 4 numbers: Cmax(<= 100), always an even number, is the maximum capacity of each station; N (<= 500), the total number
of stations; Sp, the index of the problem station (the stations are numbered from 1 to N, and PBMC is represented by the vertex 0); and M, the number of roads. The second line contains N non-negative numbers Ci (i=1,...N)
where each Ci is the current number of bikes at Si respectively. Then M lines follow, each contains 3 numbers: Si, Sj, and Tij which
describe the time Tij taken to move betwen stations Si and Sj. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print your results in one line. First output the number of bikes that PBMC must send. Then after one space, output the path in the format: 0->S1->...->Sp.
Finally after another space, output the number of bikes that we must take back to PBMC after the condition of Sp is adjusted to perfect.
Note that if such a path is not unique, output the one that requires minimum number of bikes that we must take back to PBMC. The judge's data guarantee that such a path is unique.
Sample Input:
10 3 3 5
6 7 0
0 1 1
0 2 1
0 3 3
1 3 1
2 3 1
Sample Output:
3 0->2->3 0
题目大意:每个自行车站容量为cmax,当放置车数为cmax/2时则为完美状态。现在给出cmax,车站数n,出问题的车站sp,m条互相可达的边以及它们的距离,从起点到达sp的路上会沿途调整那些需要调整的车站。此时需要求出:从出发点到问题车站所需距离最短的路线;如果有多条距离相同的路,则选择需要从起点携带车数最少的路;如果还是不唯一,则选择带回车数最少的路线。
主要思想:1. 此题是加权有向图的最短路径问题,很容易想到dijkstra,但是dijkstra无法解决第三点要求,即距离相同、带出车数相同时带回车数最小,带回车数需要在整条路径经过之后才能判断,无法在过程中立即做出选择。
所以需要使用dijkstra+dfs的方法,先找到其中一条最短路径,此时每个点到起点的最短距离都已经获得,然后利用深度优先搜索从终点反向搜索来找出所有存在的最短路径,每一次与当前保存的路径比较,从而找出其中符合要求的最优的那一条。注意反向搜索时只访问那些在其中一条最短路径上的顶点。
//dijkstra + dfs
#include <stdio.h>
#include <limits.h>
#define MAXN 501 int num[MAXN]; //各点的车数
int s[MAXN][MAXN]; //邻接矩阵表示图
int marked[MAXN]; //标记已被放松过的顶点
int distTo[MAXN]; //各点相对于起点的距离
int next[MAXN]; //下一个顶点
int path[MAXN]; //符合要求的最短路径 void relax(int v);
int min();
void dfs(int v);
void cal(int i); int n, c, sp;
int ns, nb;
//带出车的最小辆数 和 带回车的最小辆数
int n_sent = INT_MAX, n_back = INT_MAX; int main(void) {
int m, i, v, w, time;
int count = 0; scanf("%d%d%d%d", &c, &n, &sp, &m);
for (i = 1; i <= n; i++) {
scanf("%d", &num[i]);
}
for (i = 0; i < m; i++) {
scanf("%d%d%d", &v, &w, &time);
s[v][w] = time;
s[w][v] = time;
}
for (i = 1; i <= n; i++)
distTo[i] = INT_MAX; //初始化各顶点到起点的距离
distTo[0] = 0;
while (!marked[sp]) { //当sp已经被放松,则说明最短路径已找到
relax(min());
}
dfs(sp); printf("%d ", n_sent);
for (i = 0; path[i] != sp; i++) {
printf("%d->", path[i]);
}
printf("%d ", sp);
printf("%d\n", n_back); return 0;
} void relax(int v) {
int i, t; marked[v] = 1;
for (i = 0; i <= n; i++) {
t = s[v][i];
if (t == 0 || marked[i]) continue;
if (distTo[i] > distTo[v] + t) {
distTo[i] = distTo[v] + t;
}
}
} void dfs(int v) {
int i, count, t; for (i = 0; i <= n; i++) {
t = s[v][i];
//只访问已被标记过的顶点而且 该点必须是在其中一条最短路径上
if (t == 0 || !marked[i] || (distTo[i] + t != distTo[v])) continue;
next[i] = v;
dfs(i);
}
if (v != 0) return; ns = 0; //需要从起点携带的车数
nb = 0; //当前身上的车数
for (i = next[0]; i != sp; i = next[i]) {
cal(i);
}
cal(sp);
//当前这条最短路径与已经保存的最优解比较,判断是否需要更新最优路径
if (ns < n_sent || (ns == n_sent && nb < n_back)) {
count = 0;
n_sent = ns;
n_back = nb;
for (i = 0; i != sp; i = next[i]) {
path[count++] = i;
}
path[count] = sp;
}
} //计算到达每一个点时 要从起点携带的车数(是一直累加的) 和 当时身上的车数(要带回的车数)
void cal(int i) {
int x; if (num[i] > c/2) //此站车多,从中取出
nb += num[i] - c/2;
else if (num[i] < c/2) { //此站车少,补充放入
x = nb - (c/2 - num[i]);
if (x >= 0)
nb = x;
else { //身上的不够,起点携带数增加
ns += -x;
nb = 0;
}
}
} //找到距离起点最短的点,即下一个需要放松的点
int min() {
int i, min_index;
int min = INT_MAX; for (i = 0; i <= n; i++) {
if (!marked[i] && distTo[i] < min) {
min = distTo[i];
min_index = i;
}
} return min_index;
}
2. 还有一种方法是只用dfs完成,利用回溯使图中只存在一条路线,这种方法不拘束于只找最短路径,而是找出所有从起点到终点的路径,每一次都与当前保存的最优解进行比较,判断是否更新。
//dfs
#include <stdio.h>
#include <limits.h>
#define MAXN 501
int num[MAXN];
int s[MAXN][MAXN];
int marked[MAXN];
int next[MAXN];
int path[MAXN];
int n, c, sp;
int ns, nb, nt;
int n_sent = INT_MAX, n_back = INT_MAX, t_path = INT_MAX;
void cal(int i);
void dfs(int v); int main(void) {
int m, i, j, v, w, time;
int count = 0; scanf("%d%d%d%d", &c, &n, &sp, &m);
for (i = 1; i <= n; i++) {
scanf("%d", &num[i]);
}
for (i = 0; i < m; i++) {
scanf("%d%d%d", &v, &w, &time);
s[v][w] = time;
s[w][v] = time;
}
dfs(0); printf("%d ", n_sent);
for (i = 0; path[i] != sp; i++) {
printf("%d->", path[i]);
}
printf("%d ", sp);
printf("%d\n", n_back); return 0;
} void dfs(int v) {
int i, t, count; marked[v] = 1;
for (i = 0; i <= n; i++) {
if (v == sp) break;
t = s[v][i];
if (t > 0 && !marked[i]) {
next[v] = i;
dfs(i);
}
}
marked[v] = 0; //回溯,取消标记
if (v != sp) return;
nt = 0;
ns = 0;
nb = 0;
for (i = 0; i != sp; i = next[i]) {
nt += s[i][next[i]];
if (i == 0) continue;
cal(i);
}
cal(sp);
if (nt > t_path) return;
if (nt == t_path) {
if (ns < n_sent || (ns == n_sent && nb < n_back)) { }
else return;
}
n_sent = ns;
n_back = nb;
t_path = nt;
for (i = 0, count = 0; i != sp; i = next[i]) {
path[count++] = i;
}
path[count] = sp;
} void cal(int i) {
int x; if (num[i] > c/2)
nb += num[i] - c/2;
else if (num[i] < c/2) {
x = nb - (c/2 - num[i]);
if (x >= 0)
nb = x;
else {
ns += -x;
nb = 0;
}
}
}
PAT-1018 Public Bike Management(dijkstra + dfs)的更多相关文章
- PAT 1018 Public Bike Management(Dijkstra 最短路)
1018. Public Bike Management (30) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yu ...
- PAT A1018 Public Bike Management (30 分)——最小路径,溯源,二标尺,DFS
There is a public bike service in Hangzhou City which provides great convenience to the tourists fro ...
- 1018 Public Bike Management (30 分)(图的遍历and最短路径)
这题不能直接在Dijkstra中写这个第一 标尺和第二标尺的要求 因为这是需要完整路径以后才能计算的 所以写完后可以在遍历 #include<bits/stdc++.h> using n ...
- PAT 1018 Public Bike Management[难]
链接:https://www.nowcoder.com/questionTerminal/4b20ed271e864f06ab77a984e71c090f来源:牛客网PAT 1018 Public ...
- PAT Advanced 1018 Public Bike Management (30) [Dijkstra算法 + DFS]
题目 There is a public bike service in Hangzhou City which provides great convenience to the tourists ...
- PAT 1018. Public Bike Management
There is a public bike service in Hangzhou City which provides great convenience to the tourists fro ...
- 1018 Public Bike Management (30) Dijkstra算法 + DFS
题目及题解 https://blog.csdn.net/CV_Jason/article/details/81385228 迪杰斯特拉重新认识 两个核心的存储结构: int dis[n]: //记录每 ...
- PAT 甲级 1018 Public Bike Management (30 分)(dijstra+dfs,dfs记录路径,做了两天)
1018 Public Bike Management (30 分) There is a public bike service in Hangzhou City which provides ...
- PAT甲级1018. Public Bike Management
PAT甲级1018. Public Bike Management 题意: 杭州市有公共自行车服务,为世界各地的游客提供了极大的便利.人们可以在任何一个车站租一辆自行车,并将其送回城市的任何其他车站. ...
随机推荐
- 计算3的n次幂htm代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Springboot中,Tomcat启动war包的流程
将一个SpringBoot项目,打成war包 <!-- 1. 修改POM依赖 --> <dependency> <groupId>org.springframewo ...
- Python自动化运维一之psutil
1.1系统性能信息模块psutil 1.1.1下载安装psutil 1. wget https://pypi.python.org/packages/source/p/psutil/psutil- ...
- UDT的Sender和Receiver
Sender算法 数据结构和变量: Sender's Loss List:发送方的loss list用来存储丢失包的序列号,序列号来自于两个地方,一是receiver通过NAK包反馈回来,二是超时事件 ...
- POJ 3581 Prime Gap(二分)
Prime Gap Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 11009 Accepted: 6298 Descriptio ...
- andorid jar/库源码解析之okhttp3
目录:andorid jar/库源码解析 Okhttp3: 作用: 用于网络编程(http,https)的快速开发. 栗子: // okHttpClient定义成全局静态,或者单例,不然重复new可能 ...
- springboot rabbitmq 找不到队列
错误报告: org.springframework.amqp.rabbit.listener.BlockingQueueConsumer$DeclarationException: Failed to ...
- QT入门指导
罗列一些QT学习资料 1. http://www.qter.org/ 包含很多教程,包括著名的<学习之路>系列. 2. http://www.qtcn.org/bbs/index-htm- ...
- D - 小Z的加油店 线段树+差分+GCD
D - 小Z的加油店 HYSBZ - 5028 这个题目是一个线段树+差分+GCD 推荐一个差分的博客:https://www.cnblogs.com/cjoierljl/p/8728110.ht ...
- LTE基站开局流程
1.全局参数配置 MOD ENODEB :修改基站 ADD CNOPERATOR: 添加运营商 ADD CNOPERATORTA:添加跟踪区(TA) 2.设备参数配置(机柜.机框.RRU.光纤链 ...