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 题意: 杭州市有公共自行车服务,为世界各地的游客提供了极大的便利.人们可以在任何一个车站租一辆自行车,并将其送回城市的任何其他车站. ...
随机推荐
- java之 向上转型与向下转型
向上转型 class father { public void eat(){ System.out.println("father eat()"); } } class son e ...
- Java泛型和编译优化的一个例子
public class Main { public static void main(String[] args) { ArrayList<String> strList = new A ...
- 《高性能Linux服务器构建实战》——第1章轻量级HTTP服务器Nginx
第1章 轻量级HTTP服务器Nginx本章主要介绍Nginx的配置管理和使用.作为一个轻量级的HTTP服务器,Nginx与Apache相比有以下优势:在性能上,它占用很少的系统资源,能支持更多的并发连 ...
- 写给MongoDB开发者的50条建议Tip21
本系列文章翻译自<50 Tips and Tricks for MongoDB Developers>,暂时没有找到中文版,反正自己最近也在深入学习mongodb,所以正好拿来翻译一下.一 ...
- JAVA I/O 与装饰者模式UML图
- 如何使用badboy录制一个脚本并成功的导入jmeter中?
前言: 虽然,很多人已经不适用这种方式进行录制脚本了,因为不好维护.但是,还是有一些朋友在刚开始学习的过程中使用badboy. 可能有人会好奇了,人家五一都出去玩了,你在家学习吗?正巧前一阵有粉丝留言 ...
- CentOS启用iptables防火墙
centos 7默认的防火墙使用firewall,系统服务管理方式也变更了,可以通过systemctl命令控制. 可以参考这个链接 但是习惯用iptables,可以按下面的操作改下 1.关闭firew ...
- Java——Java中编码问题
在开发过程中经常会遇到一会乱码问题,不是什么大问题,但是也挺烦人的,今天来将我们开发总结的经验记录下来,希望可以给大家一些帮助. 一些概念: 字符:人们使用的记号,抽象意义上的一个符号.比如:‘1’, ...
- 斜率dp A - Print Article HDU - 3507
A - Print Article HDU - 3507 今天刚刚学习了一下斜率dp,感觉还ok,主要就是要推这个斜率,然后利用数据结构来优化. 推荐两篇写的比较好的博客,https://www.cn ...
- C. Jury Marks 思维
C. Jury Marks 这个题目虽然是只有1600,但是还是挺思维的. 有点难想. 应该可以比较快的推出的是这个肯定和前缀和有关, x x+a1 x+a1+a2 x+a1+a2+a3... x+s ...