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

为解决交通难题,某城市修建了若干条交错的地铁线路,线路名及其所属站名如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 start=new ArrayList();

//终点站集合

private List end=new ArrayList();

//输入起始站和终点站

public void input(String stationA,String stationB){

//找到该站属于哪条线

Iterator 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 process=new ArrayList();

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

minPriceProcess=calProcess;

minPrice=currPrice;

}

return;

}

if(lineIndex==length-1){

Line line=process.get(lineIndex);

currPrice+=line.price;

if(currPrice

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 stationsMap=new HashMap();

//存储线路的集合,通过路线名获得路线类对象

private Map lines=new HashMap();

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 list=new ArrayList(stationsMap.keySet());

int length=list.size();

for(int i=0;i

for(int j=i+1;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 connLines=new HashMap();

//初始化价钱列表,获得联票信息

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 connLines=new ArrayList();

//该路线的价钱

public int price;

@Override

public boolean equals(Object obj) {

return this.name.equals(((Line)obj).name);

}

@Override

public String toString() {

return this.name;

}

}

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值