蓝桥杯-地铁换乘

java实现第二届蓝桥杯地铁换乘(C++) 地铁换乘、 为解决交通难题,某城市修建了若干条交错的地铁线路,线路名及其所属站名如stations.txt所示。 线1 苹果园 .... 四惠东 线2 西直门 车公庄 .... 建国门 线4 .... 其中第一行数据为地铁线名,接下来是该线的站名。 当遇到空行时,本线路站名结束。 下一行开始又是一条新线....直到数据结束。 如果多条线拥有同一个站名,表明:这些线间可以在该站换车。 ... 阅读详情
为解决交通难题,某城市修建了若干条交错的地铁线路,线路名及其所属站名如stations.txt所示。

线1
苹果园
....
四惠东

线2
西直门
车公庄
....
建国门

线4
....

其中第一行数据为地铁线名,接下来是该线的站名。
当遇到空行时,本线路站名结束。

下一行开始又是一条新线....直到数据结束。

如果多条线拥有同一个站名,表明:这些线间可以在该站换车。

为引导旅客合理利用线路资源,解决交通瓶颈问题,该城市制定了票价策略:

1. 每条线路可以单独购票,票价不等。
2. 允许购买某些两条可换乘的线路的联票。联票价格低于分别购票。

单线票价和联合票价如 price.txt 所示。

线1 180
.....
线13 114
线1,线2 350
线1,线10 390
.....

每行数据表示一种票价
线名与票价间用空格分开。如果是联票,线名间用逗号分开。
联票只能包含两条可换乘的线路。

现在的问题是:根据这些已知的数据,计算从A站到B站最小花费和可行的换乘方案。

比如,对于本题目给出的示例数据

如果用户输入:
五棵松,奥体中心

程序应该输出:
-(线1,线10)-线8 = 565

如果用户输入:
五棵松,霍营

程序应该输出:
-线1-(线4,线13) = 440

可以看出,用户输入的数据是:起始站,终到站,用逗号分开。
程序输出了购票方案,在括号中的表示联票,短横线(-)用来分开乘车次序。
等号后输出的是该方案的花费数值。

请编程解决上述问题。
注意:
1. 我们测试您的程序时,所用数据与题目中的示例数据不同,但格式完全一样。
2. 当多个方案有相同的最小花费,输出任意一个方案即可。

要求考生把所有类写在一个文件中。
调试好后,存入与考生文件夹下对应题号的“解答.txt”中即可。
相关的工程文件不要拷入。请不要使用package语句。

另外,源程序中只能出现JDK1.5中允许的语法或调用。不能使用1.6或更高版本。

解析:

1.先处理所有的站点,求出所有线路的交叉线路,将线路看成图的一个结点,任何两条线路如果彼此交叉,则这两个线路结点相连。

2.先确定开始站和结束站在哪条线路上,然后将问题转而求从某个结点到另一个结点的路径

3.遍历以上定义的图,可以得出所有符合条件的路径,然后对每一个路径求价钱(因为有联票,所以一条路径可能有多种价钱,如存在这样一条路径:线路1-线路2-线路3-线路4,如果线路2和线路3是可以联票的,则有"线路1-(线路2,线路3)-线路4"的情况出现)

4.每次对符合要求的路径求得对应的价钱,则和最小价钱对比,比其小则保留最少价钱的方案

(备注:这道题实现的时候没有使用分支限界法,效率上打了折扣,如果用分支限界法来遍历线路图,可以提高不少性能)

java代码如下:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class js_04 {
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		String input=null;
		String[] tmp=null;
		while(scanner.hasNextLine()){
			input=scanner.nextLine();
			tmp=input.split(",");
			new js_04(tmp[0],tmp[1]);
		}
	}
	public js_04(String start,String end){
		//解析stations.txt文件,初始化站点信息
		initStations();
		//初始化线路相连信息
		initLines();
		//解析price.txt文件,初始化价格信息
		initPrice();
		input(start,end);
		startProcess();
	}
	//起始站集合
	private List<String> start=new ArrayList<String>();
	//终点站集合
	private List<String> end=new ArrayList<String>();
	//输入起始站和终点站
	public void input(String stationA,String stationB){
		//找到该站属于哪条线
		Iterator<String> it=stationsMap.keySet().iterator();
		String stations=null;
		String line=null;
		while(it.hasNext()){
			line=it.next();
			stations=stationsMap.get(line);
			if(stations.contains(stationA+",")){
				//添加到开始线路集合
				start.add(line);
			}
			if(stations.contains(stationB+",")){
				//添加到结束线路集合
				end.add(line);
			}
		}
	}
	//开始正式处理
	public void startProcess(){
		for(String st:start){
			for(String en:end){
				Line cuStart=lines.get(st);
				cuStart.isUse=true;
				process.add(cuStart);
				nfs(cuStart,lines.get(en));
				process.remove(cuStart);
				cuStart.isUse=false;
			}
		}
		//输入最终结果
		if(minPriceProcess!=null){
			System.out.print(minPriceProcess+" = ");
			System.out.println(minPrice);
		}else{
			System.out.println("不可达");
		}
	}
	//存储遍历过程
	private List<Line> process=new ArrayList<Line>(); 
	public void nfs(Line startLine,Line endLine){
		//结束找到符合要求的路径
		if(startLine.equals(endLine)){
			calPrice();
		}else{
			//遍历所有的可连接节点
			for(Line line:startLine.connLines){
				//已经遍历过则跳过
				if(line.isUse)continue;
				line.isUse=true;
				process.add(line);
				nfs(line,endLine);
				process.remove(line);
				line.isUse=false;
			}
		}
	}
	//存储最少价钱
	private int minPrice=Integer.MAX_VALUE;
	private void calPrice(){
		length=process.size();
		String calProcss="";//存储过程
		cal(0,0,calProcss);
	}
	private int length;
	private String minPriceProcess;
	//lineIndex表示当前要处理的路线的下标
	public void cal(int lineIndex,int currPrice,String calProcess){
		if(lineIndex>=length){
			if(currPrice<minPrice){
				minPriceProcess=calProcess;
				minPrice=currPrice;
			}
			return;
		}
		if(lineIndex==length-1){
			Line line=process.get(lineIndex);
			currPrice+=line.price;
			if(currPrice<minPrice){
				minPrice=currPrice;
				minPriceProcess=calProcess+"-"+line;
			}
			return;
		}else{
			Line one=process.get(lineIndex);
			Line two=process.get(lineIndex+1);
			if(currPrice+one.price>=minPrice)return;
			cal(lineIndex+1,currPrice+one.price,calProcess+"-"+one);
			int connPrice=isConnection(one,two);
			if(connPrice!=-1){//可以相连,则考虑相连的情况
				if(currPrice+connPrice>=minPrice)return;
				cal(lineIndex+2,currPrice+connPrice,calProcess+"-("+one.name+","+two.name+")");
			}
		}
	}
	//判断两条线路是否联票,是则返回联票价钱,否则返回-1
	public int isConnection(Line one,Line two){
		String key=one.name+","+two.name;
		Integer value=connLines.get(key);
		if(value==null)return -1;
		return value;
	}
	//用于保存所有的线路信息,key为线路名,value为该线路下的所有站点
	private Map<String,String> stationsMap=new HashMap<String,String>();
	//存储线路的集合,通过路线名获得路线类对象
	private Map<String,Line> lines=new HashMap<String,Line>();
	public void initStations(){
		try {
			File file=new File("stations.txt");
			BufferedReader reader=new BufferedReader(new InputStreamReader(new FileInputStream(file)));
			StringBuilder value=new StringBuilder();
			String content=null;
			String key=null;
			boolean isHead=true;//是否是线路名
			while((content=reader.readLine())!=null){
				if("".equals(content)){//一条线路读取结束
					//将线路存储起来
					Line line=new Line();
					line.name=key;
					lines.put(key, line);
					stationsMap.put(key, value.toString());
					isHead=true;
					value.delete(0, value.length());
				}else{
					if(isHead){//第一个为线路名
						key=content;
						isHead=false;
					}else{
						value.append(content).append(",");
					}
				}
			}
			Line line=new Line();
			line.name=key;
			lines.put(key, line);
			stationsMap.put(key, value.toString());
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	//初始化线路连接情况
	public void initLines(){
		List<String> list=new ArrayList<String>(stationsMap.keySet());
		int length=list.size();
		for(int i=0;i<length;i++){	
			for(int j=i+1;j<length;j++){
				//线路名
				process(list.get(i),list.get(j));
			}
		}
	}
	//处理所有交叉线路
	public void process(String l1,String l2){
		String line1=stationsMap.get(l1);
		String line2=stationsMap.get(l2);
		String[] strs=line1.split(",");
		for(String str:strs){
			if(line2.contains(str+",")){//如果两个路线有共同站点,说明交叉
				Line line01=lines.get(l1);
				Line line02=lines.get(l2);
				line01.connLines.add(line02);
				line02.connLines.add(line01);
				return;
			}
		}
	}
	//联票路线
	private Map<String,Integer> connLines=new HashMap<String,Integer>();
	//初始化价钱列表,获得联票信息
	public void initPrice(){
		try {
			File file=new File("price.txt");
			BufferedReader reader=new BufferedReader(new InputStreamReader(new FileInputStream(file)));
			String content=null;
			String[] keyValue=null;
			int price=0;
			while((content=reader.readLine())!=null){
				keyValue=content.split(" ");
				price=Integer.valueOf(keyValue[1]);
				if(keyValue[0].contains(",")){//联票
					connLines.put(keyValue[0], price);
				}else{//单条路线
					lines.get(keyValue[0]).price=price;
				}
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//自定义线路类
	class Line{
		//线路名
		public String name;
		//是否遍历过
		public boolean isUse;
		//和该路线交叉的路线
		List<Line> connLines=new ArrayList<Line>();
		//该路线的价钱
		public int price;
		@Override
		public boolean equals(Object obj) {
			return this.name.equals(((Line)obj).name);
		}
		@Override
		public String toString() {
			return this.name;
		}
	}
}


[源码和文档分享]基于QT实现的可视化地铁换乘查询系统 1.1 题目 上海的地铁交通网络已经基本成型,建成的地铁线十多条,站点上百个,现需建立一个换乘指南打印系统,通过输入起点和终点站,打印出地铁换乘指南,指南内容包括起点站、换乘站、终点站。 图形化显示地铁网络结构,能动态添加地铁线路和地铁站点 根据输入起点和终点站,显示地铁换乘指南 通过图形界面显示乘除路径 1... 阅读详情

相关推荐

地铁管理系统 c语言实现

//本程序已实现增删改和按地铁号查询,可以在查询栏目里添加按站点和按起点终点查询;

地铁换乘

【问题】 描写叙述:已知2条地铁线路,当中A为环线,B为东西向线路,线路都是双向的。经过的网站名分别例如以下,两条线交叉的换乘点用T1、T2表示。编敲代码,随意输入两个网站名称,输出乘坐地铁最少须要经过的车站数量(含输入的起点和终点,换乘网站仅仅计算一次)。 地铁线A(环线)经过车站:A1 A2 A3 A4 A5 A6 A7 A8 A9 T1 A10 A11 A12 A13 T...

weixin_34032792的博客 506

地铁换乘算法

地铁换乘算法 地铁查询算法的初步实现,仅供学习研究。 版权所有dzut@qq.com,如需转载,请保留版权。 查询注意事项: 1、应该简短输入,如:“罗湖”,不要输入“罗湖站”或“罗湖地铁站”。如要扩展,可自己二次开发。 2、目前只支持最多一次的换乘查询,多线路查询支持敬请期待。 3、目前还未收集到站点间距离数据,所以暂不支持价格查询。

华为机试--地铁换乘问题

问题描述: 描述:已知2条地铁线路,其中A为环线,B为东西向线路,线路都是双向的。经过的站点名分别如下,两条线交叉的换乘点用T1、T2表示。编写程序,任意输入两个站点名称,输出乘坐地铁最少需要经过的车站数量(含输入的起点和终点,换乘站点只计算一次)。 地铁线A(环线)经过车站:A1 A2 A3 A4 A5 A6 A7 A8 A9 T1 A10 A11 A12 A13 T2 A14 A15 

sinat_24520925的专栏 1237

基于QT5实现的上海市地铁换乘指南,数据结构

数据结构的暑期课程设计项目,在Qt Creator 4.6.2中完成。初始显示16条地铁线路图,用户选择起点和终点站,显示地铁换乘信息(按最少换乘站计算)

地铁换乘系统

地铁换乘系统 地铁换乘系统 地铁换乘系统 地铁换乘系统C++

蓝桥杯地铁换乘问题

为解决交通难题,某城市修建了若干条交错的地铁线路,线路名及其所属站名如stations.txt所示。 线1 苹果园 .... 四惠东 线2 西直门 车公庄 .... 建国门 线4 .... 其中第一行数据为地铁线名,接下来是该线的站名。 当遇到空行时,本线路站名结束。 下一行

Lves Li的专栏 2407

c语言控制台实现地铁查询功能

c语言实现地铁查询功能,采用重庆地铁作为案例,内含所有功能实现代码以及报告文档,十分详细,适合用来学习

java计算乘地铁费用_蓝桥杯-地铁换乘

为解决交通难题,某城市修建了若干条交错的地铁线路,线路名及其所属站名如stations.txt所示。线1苹果园….四惠东线2西直门车公庄….建国门线4….其中第一行数据为地铁线名,接下来是该线的站名。当遇到空行时,本线路站名结束。下一行开始又是一条新线….直到数据结束。如果多条线拥有同一个站名,表明:这些线间可以在该站换车。为引导旅客合理利用线路资源,解决交通瓶颈问题,该城市制定了票价策略:1. ...

weixin_39686230的博客 783

避开SM30维护视图的坑:自动更新字段+日志记录的5个关键配置步骤

本文深入解析了SAP ABAP开发中SM30维护视图的深度定制,聚焦于实现自动更新字段与日志记录功能。文章详细阐述了从SE54配置起点到核心编码的5个关键步骤,重点讲解了如何利用事件驱动模型(如05创建事件和01保存前事件)安全操作动态数据结构,并提供了避免常见陷阱的实用技巧,帮助开发者构建稳定可靠的自动化维护机制。

plant的博客 622

【开发必备插件】iframe嵌套报“拒绝连接请求”的本地解决方法

关键词:iframe 拒绝连接、X-Frame-Options、Chrome 插件、前端调试、Allow X-Frame-Options前几天我在本地项目里调试一个第三方网站的嵌入页面时,遇到了一个非常经典的报错:xxx.com 拒绝了我们的连接请求。熟悉的老前端们一眼就知道——这是。但对于日常开发来说,我们经常需要在本地测试 iframe 嵌套外部页面(比如嵌第三方登录页、支付页、可视化报表系统等)。而线上站点配置了或DENY时,就会直接导致 iframe 加载失败。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1540

蓝桥杯中的地铁换乘问题

如题: 为解决交通难题,某城市修建了若干条交错的地铁线路,线路名及其所属站名如stations.txt所示。 线1 苹果园 .... 四惠东 线2 西直门 车公庄 .... 建国门 线4 .... 其中第一行数据为地铁线名,接下来是该线的站名。 当遇到空行时,本线路站名结束。 下一行开始又是一条新线....直到数据结束。 如果多条线拥有同一个站名,表明:这些线间可以在该站换车。 为...

weixin_34059951的博客 287

【干货分享】高通 SA8295P PCB 设计规范指南

高通SA8295P芯片是第四代骁龙汽车数字座舱平台的核心组件,采用5nm工艺,集成高性能CPU/GPU和30TOPS算力的NPU。文章详细介绍了该芯片各接口的layout设计规范,包括USB3.1/2.0、eDP/DP、MIPI CSI/DSI、PCIe Gen3等接口的阻抗、损耗、延时等关键指标要求,为新能源汽车电子设计提供重要参考。

一只豌豆象的博客 262
上一篇: 算法学习篇(未完)
下一篇: 蓝桥杯-排日程
KeepThinking_
博客等级 码龄15年 50粉丝 39原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值