【PAT1018】 Public Bike Management 单源最短路径路径记录回溯

2024-04-05 06:18

本文主要是介绍【PAT1018】 Public Bike Management 单源最短路径路径记录回溯,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1018. Public Bike Management (30)

时间限制
400 ms
内存限制
32000 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

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
题意:

给一张图, 每个node都代表一个杭州的一个借或者还自行车站点, node上的值表示当前这个站点拥有多少量自行车, 每条边表示两个站点之间要花多少时间从一个站点到另一个站点, 给定一个有问题的站点, 求出从控制中心(PBMC)到该站点的最短路径并且使得带出去以及拿回来的自行车的数量最少.

分析:

①用最短路径算法(比如迪杰斯特拉)得到从PBMC到问题站点的所有最短路径;

②在Dijstra算法中,记录下每个节点的最优路径的上一节点,若有多个则全部记录下来;

③根据要求(带来最少带回最少),从目标节点的多个相同最短路径中找到最满足要求的一个;

④根据路径中记录的上一节点,进行回溯,直到根节点结束。

代码:

#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
using namespace std;//此代码使用前,需删除下面两行+后面的system("PAUSE")
ifstream fin("in.txt");
#define cin fin
#define MAXNUM 501
int curNum[MAXNUM]={0};			//每个station的自行车数量
int link[MAXNUM][MAXNUM]={0};
int minSumPath[MAXNUM]={0};			//达到每个station的最短路径长度
bool visited[MAXNUM]={false};
const int INF = 0x7fffffff;struct LastNode{int lastid;		//上一个节点int bikeSum;	//到当下的车辆总数int staCount;	//到当下的站点总数LastNode(int l,int b,int s){lastid=l;bikeSum=b;staCount=s;}
};vector<LastNode>  vec[MAXNUM];int c,n,s,m;void push(int target,int dataid){			//把dataid节点的统计数据导入到target节点for(int i=0;i<vec[dataid].size();i++){vec[target].push_back(LastNode(dataid,vec[dataid][i].bikeSum+curNum[target],vec[dataid][i].staCount+1));}
}void Dij(int source,int target){int cen = source;vec[0].push_back(LastNode(-1,0,0));int min,minIndex,newSumPath;while(1){visited[cen]=true;min = INF;for(int i=1;i<=n;i++){if(visited[i])continue;if(link[cen][i]!=0){newSumPath = minSumPath[cen]+link[cen][i];if(minSumPath[i]==0 || minSumPath[i]>newSumPath){		//有更小路径,更新minSumPath[i] = newSumPath;vec[i].clear();				//先清空vector再导入push(i,cen);}else if(minSumPath[i] == newSumPath){		//路径相等,添加push(i,cen);				//再原有数据基础上添加}}if(min > minSumPath[i] && minSumPath[i]!=0){min = minSumPath[i];minIndex = i;}}if(minIndex == target){		//如果找到目标节点,直接跳出循环break;}cen = minIndex;		}
}stack<int> handleIndex(int index){		//根据目标节点回溯到0号节点,将路径存储在stack中stack<int> res;int id = index;int cen = s;int staCount,bikeSum;int i;while(1){staCount = vec[cen][id].staCount-1;bikeSum = vec[cen][id].bikeSum - curNum[cen]; res.push(cen);cen = vec[cen][id].lastid;if(cen == -1)break;			//回溯到根节点 则跳出循环for(i=0;i<vec[cen].size();i++){if(vec[cen][i].staCount == staCount && vec[cen][i].bikeSum == bikeSum){		//看上一个节点的哪条数据满足条件id = i;break;}}}return res;
}int main()
{cin>>c>>n>>s>>m;if(n==0 || s==0){cout<<"0 0 0"<<endl;return 0;}int i;for(i=0;i<n;i++)cin>>curNum[i+1];int a,b;for(i=0;i<m;i++){cin>>a>>b;cin>>link[a][b];link[b][a]=link[a][b];}Dij(0,s);int plusZero = INF;int plusIndex = -1;int minusZero = -1000000;int minusIndex = -1;int index = -1;int need;			//需要带来的车辆数vector<LastNode> tt = vec[s];for(i=0;i< tt.size();i++){			//在目标节点 所有相同的最短路径中 找带来最少 带回最少的路径下标need = tt[i].staCount*c/2 - tt[i].bikeSum;if(need > 0){if(need < plusZero){plusZero = need;plusIndex = i;}}else if(need < 0){if(need > minusZero){minusZero = need;minusIndex = i;}}else{index = i;}}stack<int> res;			int come,back;if(index != -1){res = handleIndex(index);		//根据目标节点回溯到0号节点come = 0;back = 0;}else if(plusIndex != -1){res = handleIndex(plusIndex);come = plusZero;back = 0;}else{res = handleIndex(minusIndex);come = 0;back = 0-minusZero;}cout<<come<<' ';cout<<res.top();		//输出路径res.pop();while(!res.empty()){cout<<"->"<<res.top();res.pop();}cout<<" "<<back<<endl;system( "PAUSE");return 0;
}

结果:

测试点 结果 用时(ms) 内存(kB) 得分/满分
0 答案正确 2 380 12/12
1 答案正确 2 372 2/2
2 答案正确 2 376 2/2
3 答案正确 2 376 2/2
4 答案正确 1 380 2/2
5 答案错误 2 256 0/2
6 答案正确 2 376 2/2
7 答案错误 2 376 0/3
8 答案正确 2 376 2/2
9 答案正确 5 1404 1/1

还有两个Case不过,没发现原因,就先放这里吧。

这篇关于【PAT1018】 Public Bike Management 单源最短路径路径记录回溯的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/877832

相关文章

MySQL9.0默认路径安装下重置root密码

《MySQL9.0默认路径安装下重置root密码》本文主要介绍了MySQL9.0默认路径安装下重置root密码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录问题描述环境描述解决方法正常模式下修改密码报错原因问题描述mysqlChina编程采用默认安装路径,

关于Spring @Bean 相同加载顺序不同结果不同的问题记录

《关于Spring@Bean相同加载顺序不同结果不同的问题记录》本文主要探讨了在Spring5.1.3.RELEASE版本下,当有两个全注解类定义相同类型的Bean时,由于加载顺序不同,最终生成的... 目录问题说明测试输出1测试输出2@Bean注解的BeanDefiChina编程nition加入时机总结问题说明

将sqlserver数据迁移到mysql的详细步骤记录

《将sqlserver数据迁移到mysql的详细步骤记录》:本文主要介绍将SQLServer数据迁移到MySQL的步骤,包括导出数据、转换数据格式和导入数据,通过示例和工具说明,帮助大家顺利完成... 目录前言一、导出SQL Server 数据二、转换数据格式为mysql兼容格式三、导入数据到MySQL数据

关于rpc长连接与短连接的思考记录

《关于rpc长连接与短连接的思考记录》文章总结了RPC项目中长连接和短连接的处理方式,包括RPC和HTTP的长连接与短连接的区别、TCP的保活机制、客户端与服务器的连接模式及其利弊分析,文章强调了在实... 目录rpc项目中的长连接与短连接的思考什么是rpc项目中的长连接和短连接与tcp和http的长连接短

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Java访问修饰符public、private、protected及默认访问权限详解

《Java访问修饰符public、private、protected及默认访问权限详解》:本文主要介绍Java访问修饰符public、private、protected及默认访问权限的相关资料,每... 目录前言1. public 访问修饰符特点:示例:适用场景:2. private 访问修饰符特点:示例:

Python MySQL如何通过Binlog获取变更记录恢复数据

《PythonMySQL如何通过Binlog获取变更记录恢复数据》本文介绍了如何使用Python和pymysqlreplication库通过MySQL的二进制日志(Binlog)获取数据库的变更记录... 目录python mysql通过Binlog获取变更记录恢复数据1.安装pymysqlreplicat

Servlet中配置和使用过滤器的步骤记录

《Servlet中配置和使用过滤器的步骤记录》:本文主要介绍在Servlet中配置和使用过滤器的方法,包括创建过滤器类、配置过滤器以及在Web应用中使用过滤器等步骤,文中通过代码介绍的非常详细,需... 目录创建过滤器类配置过滤器使用过滤器总结在Servlet中配置和使用过滤器主要包括创建过滤器类、配置过滤

python获取当前文件和目录路径的方法详解

《python获取当前文件和目录路径的方法详解》:本文主要介绍Python中获取当前文件路径和目录的方法,包括使用__file__关键字、os.path.abspath、os.path.realp... 目录1、获取当前文件路径2、获取当前文件所在目录3、os.path.abspath和os.path.re

正则表达式高级应用与性能优化记录

《正则表达式高级应用与性能优化记录》本文介绍了正则表达式的高级应用和性能优化技巧,包括文本拆分、合并、XML/HTML解析、数据分析、以及性能优化方法,通过这些技巧,可以更高效地利用正则表达式进行复杂... 目录第6章:正则表达式的高级应用6.1 模式匹配与文本处理6.1.1 文本拆分6.1.2 文本合并6