前言:

本题是我在浏览了柳神的代码后,记下的一次半转载式笔记,不经感叹柳神的强大orz,这里给出柳神的题解地址:https://blog.csdn.net/liuchuo/article/details/52316405

题意:

有一个租借自行车的系统由n个点组成,用户可以在这n个点任意一个点借车或者还车,每个点都遵循一个共同的上限c,这里我们称一个点的状态时完美的如果这个点的车的数量为c/2,(每个点由1~n标号),而我们的出发点为0点,整个系统每次会有一个sp点发出警报,说明这个sp点的自行车数量需要调整至c/2,让我们求的时从0点出发,找一条最短的路径到达sp,调整sp以及沿途的自行车数量都达到c/2,如果车的数量不够则需要从0点调出车,(这里调整的过程是不准往回的,且到达sp点为止,后面车多了前面车少了则还是需要从0点调配出来),如果此时车多了则可以带走供给后面的车使用,到达sp点后结束,如果由多的车则全部送回,本题求的是当有一个点sp报警的时候,在最短路径的基础上,最少需要从0点调配出多少车,如果路径不唯一则选择同时送最少的车回来的路径,输出整条路径和需要送出的车数和送回的车数

分析:

本题主要由两部分构成,①首先通过dijkstra求出从0点到sp点的最短路径,在求的过程中利用一个vector数组pre[i]保存在最短路径的基础上,到达i点的所有前驱节点(因为先只考虑最短路径的情况的话可能不止有一条从0->sp的路径是最短的,每个点自然也有可能有不止一个前驱点)②通过dfs尝试每一种从0->sp的路径,计算出这条路径需要多少车need和送回多少车back,在所有的路径中选择一条need最小的,如果有并列的话,选择back最小的

注意:

虽然做题的时候我也是差不多这么想的,但是对于如何存储下每一条具体的最短路径和计算这每一条最短路径下的need和back却难住了我...还是学艺不精,我炸了,这里提醒一下需要仔细观察dfs部分的代码,这里通过一个vector数组temppath存放了每一条路径,从sp点开始,一边dfs深搜到0点,同时也将沿途的点加入到temppath中,在到达0的同时,每次都在temppath中倒着将这一条道路记录了下来,每次用完一个点之后就删去最后一个点(就像是回溯的过程)

代码:

 1 #include<iostream>
2 #include<algorithm>
3 #include<vector>
4 #include<string.h>
5 using namespace std;
6
7 const int inf = 0x3f3f3f3f;
8 int cmax, n, sp, m;
9 int minNeed = inf, minBack = inf;
10 int e[510][510], dis[510], weight[510];
11 bool vis[510];
12 vector<int> pre[510], path, temppath;
13
14 void dfs(int v){
15 temppath.push_back(v);
16 if(v == 0){
17 int need = 0, back = 0;
18 for(int i = temppath.size()-1; i >= 0; i--){
19 int id = temppath[i];
20 if(weight[id] > 0){
21 back += weight[id];
22 }else{
23 if(back > (0 - weight[id])){//需要车且有足够的车
24 back += weight[id];
25 }else{ //需要车但是车不够需要派出
26 need += ((0 - weight[id]) - back);
27 back = 0;
28 }
29 }
30 }
31 if(need < minNeed){
32 minNeed = need;
33 minBack = back;
34 path = temppath;
35 }else if(need == minNeed && back < minBack){
36 minBack = back;
37 path = temppath;
38 }
39 temppath.pop_back();
40 return;
41 }
42 for(int i = 0; i < pre[v].size(); i++)
43 dfs(pre[v][i]); //往回找起点 0
44 temppath.pop_back();
45 }
46
47 int main(){
48 memset(e, inf, sizeof(e));
49 memset(dis, inf, sizeof(dis));
50 scanf("%d%d%d%d", &cmax, &n, &sp, &m);
51 for(int i = 1; i <= n; i++){
52 scanf("%d", &weight[i]);
53 weight[i] = weight[i] - cmax/2;
54 }
55 for(int i = 0; i < m; i++){
56 int a, b;
57 scanf("%d%d", &a, &b);
58 scanf("%d", &e[a][b]);
59 e[b][a] = e[a][b];
60 }
61 dis[0] = 0;
62 for(int i = 0; i <= n; i++){
63 int u = -1, minn = inf;
64 for(int j = 0; j <= n; j++){
65 if(vis[j] == 0 && dis[j] < minn){
66 minn = dis[j];
67 u = j;
68 }
69 }
70 if(u == -1) break;
71 vis[u] = 1;
72 for(int j = 0; j <= n; j++){
73 if(vis[j] == 0 && e[u][j] != inf){
74 if(dis[j] > dis[u] + e[u][j]){
75 dis[j] = dis[u] + e[u][j];
76 pre[j].clear();
77 pre[j].push_back(u);
78 }else if(dis[j] == dis[u] + e[u][j]){
79 pre[j].push_back(u);
80 }
81 }
82 }
83 }
84 dfs(sp);
85 printf("%d 0", minNeed);
86 for(int i = path.size()-2; i >= 0; i--){
87 printf("->%d", path[i]);
88 }
89 printf(" %d\n", minBack);
90 return 0;
91 }

最新文章

  1. powerdesigner-从excel导入table模型
  2. Xamarin.iOS Unified API 注意要点
  3. 如何在JavaScript中正确引用某个方法(bind方法的应用)
  4. Intellij IDEA中使用Struts2
  5. Airbase-ng帮助
  6. 【css老版本浏览器兼容利器】ie-css3.htc
  7. spring3.2以后的cglib的jar包问题
  8. [Javascript] Advanced Console Log Arguments
  9. cache 的设计与实现--转载
  10. putty修改编码
  11. 乐在其中设计模式(C#) - 代理模式(Proxy Pattern)
  12. itext之pdf导出添加水印Java工具类
  13. Spark Streaming 快速入门
  14. Dynamics 365 Customer Engagement V9 活动源功能报错的解决方法
  15. Python txt文件读取写入字典的方法(json、eval)
  16. 只有 assignment、call、increment、decrement 和 new 对象表达式可用作语句
  17. 通过 Java 线程堆栈进行性能瓶颈分析
  18. 【Unity】8.1 Unity内置的UI控件
  19. locate命令的使用
  20. git —— 多人协作(远程库操作)

热门文章

  1. spark中map和mapPartitions算子的区别
  2. MVCAdmin项目知识点记录
  3. .net5+nacos+ocelot 配置中心和服务发现实现
  4. Elasticsearch.Net
  5. Python高级语法-私有属性-魔法属性(4.7.2)
  6. Numpy的学习3-索引
  7. SpringBoot进阶教程(六十七)RateLimiter限流
  8. Demo分享丨看ModelArts与HiLens是如何让车自己跑起来的
  9. 【C++】C++之类型转换
  10. ES标签搜索并解决评分排序问题