地铁换乘、

为解决交通难题,某城市修建了若干条交错的地铁线路,线路名及其所属站名如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语句。

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;
}
}
}

C++:

#include<iostream>
using namespace std;
#define LEN 50
typedef struct stations{
char name[20];
int len;
int roads[50];
struct stations *left;
struct stations *right;
}Stations; typedef struct etree{
int value;
int roadNum;
struct etree *father;
int childnum;
}ETree; typedef struct queue{
ETree *tie;
struct queue *next;
}Queue; void pushQueue(Queue &head, ETree *&etree){
Queue *p=head.next,*q=&head;
while(p!=NULL && (p->tie->value<etree->value)){
q=p;
p=p->next;
}
q->next=(Queue*)malloc(sizeof(Queue));
q->next->tie=etree;
q->next->next=p;
}
void freeEtree(ETree *q){
ETree *p;
while(q->childnum==0){
p=q;
q=q->father;
free(p);
if(q!=NULL)
q->childnum--;
else
break;
}
} void freeAll(Stations *&head){
if (head!=NULL){
freeAll(head->left);
freeAll(head->right);
free(head);
}
} void showBest(ETree *h,int price[][LEN],char roadName[][20],int roadNum){
if(h!=NULL){
if (h->faher==NULL){
printf("%s",roadName[h->roadNum]);
}
else{
int j;
j=h->roadNum;
if (h->value==(price[j][j]+h->father->value)){
showBest(h->father,price,roadName,roadNum);
if (price[j][roadNum]){
printf("-(%s,%s)",roadName[j],roadName[price[j][roadNum]-1]); }
else
printf("-%s",roadName[j]);
}
else{
showBest(h->father->father,price,roadNme,roadNum);
printf("-(%s,%s)",roadName[h->father->roadNum],roadName[j]);
}
}
}
} inline int compares(char s1[],int n1,chr s2[],int n2){
if (n1!=n2)
return n1-n2;
return strcmp(s1,s2);
}
boll findStation(Stations* &head,Stations* &p,char s[]){
int len=strlen(s);
int t;
Stations q;
p=head;
while (n!=NULL){
q=p;
t=compares(s,len,p->name,p->len);
if (t<0)
p=p->left;
else
retrn true;
}
p=q;
return false;
} void insert(Stations* &head,char s[],int road,int price[][LEN]{
Stations *p,*q;
int t;
t=strlen(s);
if(s[t-1]=='\n')
s[t-1]='\0';
if(head==NULL){
p=(Stations *)malloc(sizeof(Stations));
p->left=NULL;
p->rght=NULL;
strcpy(p->name,s);
p->len=strlen(s);
p->road[0]=1;
p->road[1]read;
head=p;
}
else{
if (findStation(head,p,s)){
p->roads[0]++;
t=p->roads[0];
p->roads[t]=road;
for(t--;t>0,t--){
price[p->road[t]][road]=-1;
price[road][p->road[t]]=-1;
}
}
else{
q=p;
p=(Stations *)malloc(sizeof(Stations));
p->left=NULL;
p->right=NULL;
strcpy(p->name,s);
p->len=strlen(s);
p->road[0]=1;
p->road[1]=road;
t=compares(s,p->len,q->name,q->len);
if(t<0)
q->left=p;
else
q->right=p;
}
}
} int GetRoadNum(char *r,char roadName[][20],int road Num){
for (int i=0;i<roadNum;i++)
if (strcmp(roadName[i],r)==0)
return i;
return 0;
} void main()
{
//[roadnum][roadnum+1]
int price[LEN][LEN]={0};
char roadName[LEN][20];
int i,j,k,t;
char line[20];
int roadNum;
Stations *head=NULL;
FILE *fp;
if((fp=fopen("stations.xt","r"))==NULL){
printf("找不到stations文件\n");
return;
}
roadNum=0;
while(!feof(fp)){
fscanf(fp,"%s%*c",roadName[roadNum]);
fgets(line,19,fp);
while(!feof(fp)&&line[0]!='\n'){
insert(head,line,roadNum,price);
fgets(line,19,fp);
}
roadNum++;
}
roadNum++;
}
insert(head,line,roadNum-1,price);
fclose(fp);
if ((fp=fopen("price.txt","r"))==NULL){
printf("找不到price文件");
}
while (!feof(fp)){
fscanf(fp,"%s,line);
fscanf(fp,"%d",&k);
for(t=0;line[t]!='\0'&&line[t]!=",";t++);
if (line[t]==','){
line[t]='\0';
i=GetRoadNum(line,roadName,roadNum);
j=GetRoadNum(line+t+1,roadName,roadNm);
price[i][j]=k;
price[j][i]=k;
if (price[i][i]>k){
price[i][roadNum]=j+1;
}
if (price[j][j]>k){
price[j][j]=k;
price[j]roadNum]=i+1;
}
}
else{
i=GetRoadNum(line,roadName,roadNum);
price[i][i]=k;
}
} fclose(fp); char starts[20]={"五棵松"},ends[20]="奥体中心"};
Stations *sroad,*eroad;
Queue Qhead, *h;
Etree *p,*q;
while(true){
char Flag[LEN]={0};//为-1表示目标,为0表示尚未发生过扩展
Qhead.next=NULL;
Qhead.tie=NULL;
scanf("%[^,\n]s",starts);
if (getchar()!=',')
break;
scanf("%[^\n]s",ends);
getchar();
if (!findStation(head,sroad,starts)){
printf("未找到%s的匹配项\n",starts);
continue;
}
if (!findStation(head,eroad,ends)){
printf("未找到%s的匹配项\n",ends);
continue;
}
for (i=1;i<=sroad->roads[0];i++){
p=(ETree*)malloc(sizeof(ETree));
p->father=NULL;
p->childnum=0;
p->roadNum=sroad->roads[i];
p->value=price[p->roadum][p->roadNum];
pushQueue(Qhead,p);
}
for (i=1;i<=eroad->roads[0];i++){
Flag[eroad->roads[i]]=-1;
}
while(Qhead.next!=NULL){
h=Qhead.next;
q=h->tie;
if (Flag[q->roadNum]==-1){
break;
}
Qhuad.next=Qhead.next->next;
i=q->roadNum;
if (Flag[i]!=1){
for(j=0;j<roadNum;j++){
if (price[i][j]){
q->childnum++;
p=(ETree*)malloc(sizeof(ETree));
p->father=q;
p->childnum=0;
p->roadNum=j;
k=price[j][j]>0){
if(price[i][j]>0){
if(q->father!=NULL)
t=price[i][j]+q->father->value;
else
t=price[i][j];
if (k>t)
k=t;
}
p->value=k;
pushQueue(Qhead,p);
}
}
Flag[i]=1;
}
freeETree(h->tie);
free(h);
}
if (Qhead.next!=NULL){
showBest(q,price,roadName,roadNum);
printf("=%d\n",q->value);
}
else
printf("此路不通\n");
for(;Qhead.next!=NULL;){
h=Qead.next;
Qhead.nexQhead.next->next;
freeETree(h->tie);
free(h);
}
}
freeAll(head);
}

最新文章

  1. Liunx面试题
  2. Java,Android 项目导入Eclipse常见错误
  3. yii中sphinx索引配置解析
  4. Zabbix 集成 OneAlert 实现全方位告警
  5. windows 触发桌面图标布局保存
  6. windows完全支持C++11的轻量级编译器(官网MinGW和非官方的MinGW-builds)
  7. who is the best?
  8. 极化码之tal-vardy算法(2)
  9. Tomcat多域名访问
  10. studio安装插件
  11. list映射
  12. TypeScript语法学习--基本类型
  13. why-the-default-authentication-hadoop-is-unsecured ?
  14. sin n次方 x 的降幂公式
  15. Eclipse 如何查看源代码
  16. list 的 增 删
  17. [转载]WebService使用的一些总结
  18. Spark1.6 Idea下远程调试
  19. ActiveMQ基本详解与总结&amp; 消息队列-推/拉模式学习 &amp; ActiveMQ及JMS学习
  20. 在Android 开发中使用 SQLite 数据库笔记

热门文章

  1. HDU 2004 (水)
  2. 将微服务运行在docker上遇到的问题一
  3. 基于 abp vNext 和 .NET Core 开发博客项目 - 完善与美化,Swagger登场
  4. 「雕爷学编程」Arduino动手做(17)---人体感应模块
  5. node的querystring
  6. Java POI 读取Excel数据转换为XML格式
  7. iOS开发常用技能点(持续更新中。。。)
  8. 蓝桥杯 试题 历届试题 对局匹配 DP解决
  9. Higher-Order Functions Fundamentals
  10. 记一次 React Native 大版本升级过程——从0.40到0.59