Advertisement

java实现第二届蓝桥杯地铁换乘(C++)

阅读量:

地铁换乘、

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

全部评论 (0)

还没有任何评论哟~