北京地铁乘坐线路查询

标题北京地铁乘坐线路查询

【问题描述】

编写一个程序实现北京地铁最短乘坐(站)线路查询,输入为起始站名和目的站名,输出为从起始站到目的站的最短乘坐站换乘线路。注:1. 要求采用Dijkstra算法实现;2)如果两站间存在多条最短路径,找出其中的一条就行。

【输入形式】

文件bgstations.txt为数据文件(可从课程网站中课程信息处下载),包含了北京地铁的线路及车站信息。其格式如下:

<地铁线路总条数>

<线路1> <线路1站数>

<站名1> <换乘状态>

<站名2> <换乘状态>

<线路2> <线路2站数>

<站名1> <换乘状态>

<站名2> <换乘状态>

说明:文件第一行为地铁总线路数;第二行第一个数为某条地铁线线号(如,1为1号线),第二个数为该条地铁线的总站数(如1号线共有23站),两数之间由一个空格分隔;第三行两个数据分别为地铁站名及换乘状态(0为非换乘站,1为换乘站),两数据间由一个空格分隔;以下同,依次为该线地铁其它站信息。在一条线路信息之后是下条地铁线路信息,格式相同。若某条地铁线为环线,则首站与末站信息相同(如北京地铁2号线,首站信息“西直门 1” ,末站信息为“西直门 1”)。例如本题提供的bgstations.txt文件(可从课程网站中课程信息处下载)内容如下:

13

1 23

苹果园 0

古城 0

八角游乐园 0

八宝山 0

玉泉路 0

五棵松 0

万寿路 0

公主坟 1

军事博物馆 1

木樨地 0

南礼士路 0

复兴门 1

西单 1

2 19

西直门 1

积水潭 0

鼓楼大街 1

西直门 1

该文件表明当前北京地铁共有13条线路(不含郊区线路),接着为每条线路信息。

打开当前目录下文件bgstations.txt,读入地铁线路信息,并从标准输入中读入起始站和目的站名(均为字符串,各占一行)。

【输出形式】

输出从起始站到目的站的乘坐信息,要求乘坐站数最少。换乘信息格式如下:

SSN-n1(m1)-S1-n2(m2)-…-ESN

其中:SSN和ESN分别为起始站名和目的站名;n为乘坐的地铁线路号,m为乘坐站数。
【样例输入】

西土城

北京西站

【样例输出】

西土城-10(1)-知春路-13(2)-西直门-4(2)-国家图书馆-9(4)-北京西站

(或西土城-10(1)-知春路-13(2)-西直门-2(1)-车公庄-6(2)-白石桥南-9(3)-北京西站)

【样例说明】

打开文件bgstations.txt,读入地铁线路信息,并从标准输入中读入查询起始站名为“西土城”,目的站名为“北京西站”。程序运行结果两站间最少乘坐站数的乘坐方式为“西土城站乘坐10号线1站至知春路站换乘13号线乘坐2站至西直门站换乘4号线乘坐2站至国家图书馆站换乘9号线乘坐4站至北京西站”。本样例存在两条最少站数的乘坐方式,只要找出一条就可以。

【评分标准】

对于同一个起始站和目的站,如果存在多条最少站数的乘坐方式,只要找出其中一条就可以。测试点全通过得满分。

下面上代码:

#include
#include

#define max_length 20//表示字符串长度
#define max_station 500//表示最多地铁站数
#define INFINITY 32767//大数

struct station{
	char name[max_length];//站点名称 
	int state;//换乘状态,0 非换乘,1 换乘 
}sta[max_station];
//存站点

struct weight{
	int wei;//权重,可以理解为两站点之间的相差站数 
	int line;//两站点间的线路所在线号 
}vertex[max_station+5][max_station+5];
//存边权重

FILE *in;

int k,spath[max_station];//spath[]数组存路径

void read(){
	in=fopen("bgstations.txt","r");
	int max_line;
	fscanf(in,"%d",&max_line);
	int i,j,v1,v2;
	//初始化 
	for(i=1;i<=max_station;i++){
		for(j=1;j<=max_station;j++){
			vertex[i][j].wei=INFINITY;
			vertex[i][j].line=0;
		}
	}//初始化结束 
	/* 初始化很重要,曾多次掉坑 */
	
	for(i=1;i<=max_line;i++){
		int line_num,station_num;
		v1=v2=-1;//表示前后两个站点
		fscanf(in,"%d%d",&line_num,&station_num);
		for(j=1;j<=station_num;j++){
			//判断该站点是否是之前读过
			char s[max_station];
			int ii,flag=1,change;
			fscanf(in,"%s%d",s,&change);
			for(ii=1;ii<=k;ii++){
				if(strcmp(sta[ii].name,s)==0){//读过
					flag=0;
					v1=ii;
					break;
				}
			}
			if(flag){//没读过
				k++;
				strcpy(sta[k].name,s);
				sta[k].state=change;
				v1=k;
			}
			if(v2!=-1){//表示当前读入的v1点不是该线路的第一个点
				vertex[v1][v2].line=vertex[v2][v1].line=line_num;
				vertex[v1][v2].wei=vertex[v2][v1].wei=1;
			}
			v2=v1;//记录当前点,之后读入可以用来比较
		}
	}
	fclose(in);
}

//Dijkstra算法
void Dijkstra(int origion,int destination){
	int i,j,v=0;
	int minweight;
	int found[max_station+5]; // 标记是否已经确定最短距离
	memset(found,0,sizeof(found[0])*max_station); // 初始化
	int sweight[max_station+5]; // 存最短距离
	
	for(i=1;i<=max_station;i++){ // 初始化
		sweight[i]=vertex[origion][i].wei;
		spath[i]=origion;// i 的前驱结点为 origion 
	}
	sweight[origion]=0;//标记距离 
	found[origion]=1;//标记已找到 
	for(i=1;i0) && (minweight+vertex[v][j].wei=1;i--){
		if(flag == 0) {
			printf("%s-%d",sta[temp[i]].name,vertex[temp[i]][temp[i-1]].line);
			flag=1;
		}
		else{
			if(vertex[temp[i+1]][temp[i]].line==vertex[temp[i]][temp[i-1]].line){
				cnt++;
			}
			else{
				printf("(%d)-",cnt);
				cnt=1;
				flag=0;
				i++;
			}
		}
	}
	printf("(%d)-%s\n",cnt,sta[destination].name);
}

int main()
{
	read();
	char start[max_length],end[max_length];
	scanf("%s%s",start,end);
	int origion=0,destination=0,cnt=0;
	int i;
	for(i=1;i<=k;i++){
		if(strcmp(sta[i].name,start) = = 0){
			origion=i;
			cnt++;
		}
		if(strcmp(sta[i].name,end) = = 0){
			destination=i;
			cnt++;
		}
		if(cnt==2) break;
	}
	Dijkstra(origion,destination);
	print(origion,destination);
	return 0;
}

以上就是全部代码,由于刚刚接触算法,所以对Dijkstra算法并不熟悉,特记在此,便于日后回顾总结。

你可能感兴趣的:(C语言)