PAT(甲级)渡劫(一)-Public Bike Management

题目描述:

There is a public bike service in Hangzhou City which provides great convience to the tourists from all over the world. One may rent a bike at any station and return it to any other station in the city.
The Public Bike Management Center(PBMC) Keeps monitoring the real-time capacity of all the station. 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 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

输入例子:

10 3 3 5
6 7 0
0 1 1
0 2 1
0 3 3
1 3 1
2 3 1

输出例子

3 0->2->3 0

算法分析:

​ 这道题用dijkstra过不了。**如果只有Dijkstra是不可以的,因为minTake和minBring在路径上的传递不满足最优子结构,不是简单的相加的过程,只有在所有路径都确定了之后才能去选择最小的need和最小的back。**所以我们可以用dfs搜索所有最短路,找出最优解

代码如下:

#include <iostream>
#include <cstdio>
#include <vector>
#define INF 99999999
using namespace std;struct station{ // 自行车站结构体int time,bike;  // 到达该站的时间以及该站的自行车数量station(){}station(int bike):bike(bike){   // 初始化到达该站的时间为无穷,表示不可达time = INF;}
};struct edge{int next;   // 指向下一个结点的编号int length;edge(int a,int b):next(a),length(b){}
};vector<edge> G[510];    // 邻接链表
station st[510];        // 保存车站信息bool visited[510] = {false};   // 访问标记数组vector<int> path;   // 路径数组
vector<int> anspath;    // 保存最后的路线数组// 初始化
// 大写表示最终结果,小写表示操作变量,
int Sum = INF,sum = 0;      // 记录花费的时间
int Bring = INF,bring = 0;  // 记录需要从PBMC携带的自行车数量
int Take = INF,take = 0;    // 记录我们需要带回PBMC自行车的数量int Cmax,N,Sp,M;    // Cmax: 一个站的最大容量// N: 站的数量// Sp: 目的站的编号// M: 路的数量void dfs(int a){if(sum > Sum) return ;if(a == Sp){    // 当为终点时,判断是否为最优解if(Sum > sum || (Sum == sum && (Bring > bring || (Bring == bring && Take > take)))){Sum = sum;Bring = bring;Take = take;anspath = path;}return ;}for(int i = 0 ; i < G[a].size(); i++){int next = G[a][i].next,length = G[a][i].length;int tempbring = bring,temptake = take,tempsum = sum;    // 保存值,便于回溯if(visited[next] == true) continue;if(st[next].time >= st[a].time + length){// 若下一点可达visited[next] = true;take += st[next].bike;if(take < 0){bring -= take;  // 若take为负,表示需要带回take = 0;}sum += length;  // 累加所需经过的时间st[next].time = st[a].time + length;path.push_back(next);  // 将该结点加入路径dfs(next);  // 继续深度遍历该结点visited[next] = false;  // 回溯bring = tempbring;take = temptake;sum = tempsum;path.pop_back();}}
}int main(){scanf("%d%d%d%d",&Cmax,&N,&Sp,&M);Cmax /= 2; // 最佳存储量为最大容量的一半int bike;// 初始化起点0,设置时间与bike数量为0,时间为0可达st[0] = station(0);st[0].time = 0;for(int i = 1 ; i <= N ; i++){// 输入每个站的自行车存储量scanf("%d",&bike);st[i] = station(bike-Cmax); // bike为正则需带回,为负则需调配}int a,b,c;for(int i = 0 ; i < M ; i++){// 输入每条路的信息scanf("%d%d%d",&a,&b,&c);G[a].push_back(edge(b,c));G[b].push_back(edge(a,c));}dfs(0);printf("%d 0",Bring);for(int i = 0 ; i < anspath.size() ; i++){printf("->%d",anspath[i]);}printf(" %d",Take);return 0;
}

运行结果:

其他答案:

#include <iostream>
#include <cstdio>
#include <vector>using namespace std;const int inf = 1e9;
int perfect,n,sp,m;
int c[505];                 // 记录车站现存的自行车,下标代表车站编号
int g[505][505] = {0};      // 邻接矩阵
bool visited[505] = {true}; // 访问标记数组,初始化为false
vector<int> tPath,path;     // path存储最佳路径,tpath为临时变量
int len = 0,minLen = inf;
int need = 0,back = 0;      // need表示需要带去的自行车,back表示需要带回的自行车
int minNeed = inf,minBack = inf;    // 记录最少的need和backvoid dfs(int s){if(s == sp){// 如果是终点,若有多条,判断是否为最优解if(len < minLen){path = tPath;minLen = len;minNeed = need;minBack = back;}else if(need < minNeed || (need == minNeed && back < minBack)){path = tPath;minNeed = need;minBack = back;}return;}for(int i = 1 ; i <= n ; i++){if(!visited[i] && g[s][i]){ // 访问s结点的邻接结点int tn = need,tb = back;    // 暂存此时的need,back,因为后面需要修改,便于后面回溯恢复到原来的状态if(c[i] < perfect){if(back >= perfect - c[i]) back -= perfect - c[i];else{need += perfect - c[i] - back;back = 0;}}else{back += c[i]-perfect;}visited[i] = true;len += g[s][i];tPath.push_back(i);if(len <= minLen) dfs(i);// 回溯need = tn,back = tb;visited[i] = false;len -= g[s][i];tPath.pop_back();}}
}int main(){//freopen("in.txt","r",stdin);scanf("%d%d%d%d",&perfect,&n,&sp,&m);perfect /= 2;   // 最大容量的一半表示最佳容量for(int i = 1 ; i <= n ; i++)   // 输出每个车站的自行车的数量scanf("%d",c+i);for(int i = 0 ; i < m ; i++){int s1,s2,e;scanf("%d%d%d",&s1,&s2,&e);g[s1][s2] = g[s2][s1] = e;}dfs(0);printf("%d 0",minNeed); // 输出最少需要带去的车辆数目for(int i = 0 ; i < path.size() ; i++)  // 输出最佳路径printf("->%d",path[i]);printf(" %d",minBack);  // 输出最少需要带回的车辆数目return 0;
}

运行结果:

PAT(甲级)渡劫(一)-Public Bike Management相关推荐

  1. 【PAT - 甲级 - 1018】Public Bike Management (带权最短路,多条最短路中加条件,DFS)

    题干: 链接:https://www.nowcoder.com/questionTerminal/4b20ed271e864f06ab77a984e71c090f 来源:牛客网 There is a ...

  2. PAT 甲级 1018. Public Bike Management

    原题传送门 此题就是理解题意很麻烦- dfs或者 dijkstra dfs: #include <iostream> #include <vector> using names ...

  3. PAT 甲级 1018 Public Bike Management

    目录 Dijstra+堆优化+DFS SFPA+DFS Dijstra+堆优化+DFS priority_queue 单词要拼对,哈哈. #include <bits/stdc++.h> ...

  4. 1018 Public Bike Management (30 分) 【难度: 难 / 知识点: 图论 最短路 图的遍历】

    https://pintia.cn/problem-sets/994805342720868352/problems/994805489282433024 需要注意的是,往回拉的车,是不可以补我们去的 ...

  5. PAT甲级真题目录(按题型整理)(转自柳神)

    转载自:https://www.liuchuo.net/archives/2502?tdsourcetag=s_pcqq_aiomsg 最短路径 1003. Emergency (25)-PAT甲级真 ...

  6. PAT甲级训练合集(1-70)

    本章题解跳转 考点 P1001 数字的数组表示和处理 P1002 多项式的数组表示和处理 P1003 深度优先搜素 P1004 深度优先搜素 P1005 哈希表 P1006 P1007 数组子区间求和 ...

  7. 【PAT甲级】A1001-A1050刷题记录

    文章目录 A1001 A+B Format (20 分) 0.25 ★(一元多项式加法) A1002 A+B for Polynomials (25 分) 0.21 (单源最短路Dijkstra+边权 ...

  8. PAT甲级1001~1025

    PAT甲级1001~1025 1001 A+B Format (20 分) 1002 A+B for Polynomials (25 分) 1003 Emergency (25 分) 1004 Cou ...

  9. 刷PAT甲级的各题思路、细节以及遇到的问题记录

    1001 A+B Format (20分) 因为一定会用到字符串,而string非常好用,但是用的时候一定要注意不能越界访问,否则会在运行时出现abort() has been called. 100 ...

最新文章

  1. java stringbuilder换行_初遇Java StringBuffer 和 StringBuilder 类利用 StringBuilder 给TextView实现换行处理...
  2. Python合并两个List
  3. android系统(9)---android工具网站
  4. MySQL索引类型及创建
  5. postman 的基础使用
  6. ICCV'21 Oral|拒绝调参,显著提点!检测分割任务的新损失函数RS Loss开源
  7. mysql语句解析_MYSQL中SQL执行分析
  8. python机器学习——文本情感分析(英文文本情感分析)
  9. Word VBA查找表格单元格的第一段
  10. WIN10 激活系统
  11. 手把手教你领取永久免费服务器
  12. linux中重要文件夹介绍
  13. 华为 编程语言实验室,薪水_作为实验室科学家学习编程
  14. 移动云瞄准“一流云商”焕新出发
  15. Xilinx vivado 常用IP核使用
  16. 第四章案例研究--------------------- 基于业务驱动的企业安全架构(翻译,原作者John Sherwood ;Andrew Clark; David Lynas)---仅学习使用
  17. Typora护眼绿和夜色两种背景
  18. GitHub上买房攻略开源,一夜之间涨星近千,网友说:正好需要!
  19. 苏宁易购董事会改选并聘任张近东为名誉董事长;ASSASSINA莎辛那首个香氛沙龙闪现网红玻璃森林 | 知消...
  20. CheckStyle:Checks之标准Checks

热门文章

  1. 狂神Docker通俗易懂学习笔记2
  2. 剪辑过的视频md5会改变
  3. Excel,根据一列的子集进行筛选
  4. JVM 双亲委派机制(通俗易懂)
  5. 24款神级插件,让你的 vscode更牛
  6. Deep Learning Hierarchical Representations for Image Steganalysis【Ye-Net:图像隐写分析的深度学习层次表示】
  7. [心情]享受堕落的乐趣
  8. 0725(016天 多态复习 java中级-抽象类01)
  9. jekyll部署到服务器
  10. Spark内核设计的艺术:架构设计与实现——前言