编程思维训练4:地铁导航

有3条地铁线,输入两个站点,输出一条可行的路线。例如下面1号线、2号线、3号线:

1号线:

苹果园,古城,八角游乐园,八宝山,玉泉路,五棵松,万寿路,公主坟,军事博物馆,木樨地,南礼士路,复兴门,西单,天安门西,天安门东,王府井,东单,建国门,永安里,国贸,大望路,四惠,四惠东

2号线:

积水潭,鼓楼大街,安定门,雍和宫,东直门,东四十条,朝阳门,建国门,北京站,崇文门,前门,和平门,宣武,长椿街,复兴门,阜成门,车公庄,西直门

3号线:

安河桥北,北宫门,西苑,圆明园,北京大学东门,中关村,海淀黄庄,人民大学,魏公村,国家图书馆,动物园,西直门,新街口,平安里,西四,灵境胡同,西单站,宣武门,菜市口,陶然亭,北京南站,马家堡,角门西,公益西桥,新宫,西红门,高米店北,高米店南,枣园,清源路,黄村西大街,黄村火车站,义和庄,生物医药基地,天宫院。

1号线和2号线的交点站:复兴门、建国门。

2号线和3号线的交点站:西直门。

1号线和3号线之间没有交点站。(为了测试中转效果,将3号线“西单”改为“西单站”,这样1号线和3号线之间就没有交点站了)

程序如下:

#include<stdio.h>
#include<malloc.h>
#include<string.h>
#define LEFT2RIHGT 0
#define RIGHT2LEFT 1
void outline(int line,int begin,int end,char **s[3],int nDirection,int PRINTJOINT,int ADDTAG);
int getJoinpoint(int begin,int end,char **s[3],int N[3],int *t[3]);
int getN(char *s) { //统计站点数
	int N=1;
	char *p=s;
	while(*p!='\0') if(*p++==',')N++;
	return N;
}
int main() {
	char S1[]="苹果园,古城,八角游乐园,八宝山,玉泉路,五棵松,万寿路,公主坟,军事博物馆,木樨地,南礼士路,复兴门,西单,天安门西,天安门东,王府井,东单,建国门,永安里,国贸,大望路,四惠,四惠东";
	char S2[]="积水潭,鼓楼大街,安定门,雍和宫,东直门,东四十条,朝阳门,建国门,北京站,崇文门,前门,和平门,宣武,长椿街,复兴门,阜成门,车公庄,西直门";
	char S3[]="安河桥北,北宫门,西苑,圆明园,北京大学东门,中关村,海淀黄庄,人民大学,魏公村,国家图书馆,动物园,西直门,新街口,平安里,西四,灵境胡同,西单,宣武门,菜市口,陶然亭,北京南站,马家堡,角门西,公益西桥,新宫,西红门,高米店北,高米店南,枣园,清源路,黄村西大街,黄村火车站,义和庄,生物医药基地,天宫院";
	char **s1,**s2,**s3;
	char *S[3]= {S1,S2,S3};
	int  *t[3];
	char **s[3]= {s1,s2,s3};
	char *p,*q;
	char begin[20],end[20];
	int i,j,k,prev,next;
	int N[3];
	int beginI,beginID,endI,endID;
	int njoin=0;
	for(i=0; i<3; i++) {
		//创建动态二维数组
		N[i]=getN(S[i]);
		s[i]=(char **)malloc(N[i]*sizeof(char*));
		t[i]=(int *)malloc(N[i]*sizeof(int*));//是否交点站的记录表
		for(j=0; j<N[i]; j++) {
			s[i][j]=(char *)malloc(sizeof(char)*20);
			t[i][j]=0;
		}

		//初始化数组
		p=S[i];
		j=0;
		q=s[i][j];
		while(*p!='\0') {
			if(*p!=',')
				*q++=*p;
			else {
				*q='\0';
				j++;
				q=s[i][j];
			}
			p++;
		}
	}

	//查找线路转车站点
	for(i=0; i<2; i++)//线路
		for(j=i+1; j<3; j++) {
			for(prev=0; prev<N[i]; prev++)
				for(next=0; next<N[j]; next++)
					if(strcmp(s[i][prev],s[j][next])==0)
						t[i][prev]=t[j][next]=++njoin;
		}
	//printf("输入起点:");
	//gets(begin);
	//printf("输入终点:");
	//gets(end);
	//为了测试方便,直接给出起止站点
	strcpy(begin,"王府井");		//1号线:王府井
	strcpy(end,"东直门");			//1号线:军事博物馆,2号线:东直门,3号线:圆明园
	beginI=beginID=-1;
	for(i=0; i<3; i++) { //线路
		for(j=0; j<N[i]; j++) {
			if(strcmp(s[i][j],begin)==0) {
				beginI=i;
				beginID=j;
				break;
			}
		}
		if(beginI!=-1)break; //找到站点退出循环
	}
	endI=endID=-1;
	for(i=0; i<3; i++) { //线路
		for(j=0; j<N[i]; j++) {
			if(strcmp(s[i][j],end)==0) {
				endI=i;
				endID=j;
				break;
			}

		}
		if(endI!=-1)break; //找到站点退出循环
	}

	//搜索所在地铁线路、位置
	if(beginI==endI) { //相同线路
		outline(beginI,beginID,endID,s,LEFT2RIHGT,1,0);
	} else { //不同线路
		k=getJoinpoint(beginI,endI,s,N,t); //查找交点
		if(k>0) {
			outline(beginI,beginID,k/100,s,LEFT2RIHGT,1,1); // k/100是第1条线路的交点位置
			outline(endI,endID,k%100,s,RIGHT2LEFT,0,0);	// k%100是第2条线路的交点位置
		} else { //没有交点站,需要查中间过渡地铁线
			for(i=0; i<3; i++) {
				k=k2=-1;
				if(i!=beginI && i!=endI) {
					k=getJoinpoint(beginI,i,s,N,t);
					k2=getJoinpoint(i,endI,s,N,t);
					if(k>0 && k2>0) { //找到可中转的地铁线i
						outline(beginI,beginID,k/100,s,LEFT2RIHGT,1,0); // beginID至k/100
						outline(i,k2/100,k%100,s,RIGHT2LEFT,0,0);  // k2/100至k%100
						outline(endI,endID,k2%100,s,RIGHT2LEFT,0,0); //k2%100至endID
						break;
					}
				}
			}
		}
	}
}
//输出路线
// nDirection	1 begin输出到end		0 从end输出到begin
// PRINTJOINT	1输出end 			0 不输出end
// ADDTAG		中转站名称外是否加一对括号
void outline(int line,int begin,int end,char **s[3],int nDirection,int PRINTJOINT,int ADDTAG) {
	int i;
	printf("[%d]",line+1);
	if(nDirection==0) { //指向end
		if(begin<=end) {
			for(i=begin; i<end; i++)
				printf("%s ",s[line][i]);
		} else {
			for(i=begin; i>end; i--)
				printf("%s ",s[line][i]);
		}
		if(PRINTJOINT)
			if(ADDTAG)printf("(%s) ",s[line][end]);
			else printf("%s ",s[line][end]);
	} else {	//指向begin
		if(PRINTJOINT)
			if(ADDTAG)printf("(%s) ",s[line][end]);
			else printf("%s ",s[line][end]);
		if(begin<=end) {
			for(i=end-1; i>=begin; i--)
				printf("%s ",s[line][i]);
		} else {
			for(i=end+1; i<=begin; i++)
				printf("%s ",s[line][i]);
		}
	}
	printf("[%d]",line+1);
}
//查找交点
int getJoinpoint(int begin,int end,char **s[3],int N[3],int *t[3]) {
	int i,j,k;
	for(i=0; i<N[begin]; i++) {
		if(t[begin][i]>0) {
			for(j=0; j<N[end]; j++)
				if(t[end][j]==t[begin][i])
					return i*100+j; //将两个交点i和j转换成一个整数返回
		}
	}
	return -1;
}

输出结果:

[1]王府井  天安门东  天安门西 西单 (复兴门)[1] [2] 长椿街 宣武 和平门 前门 崇文门 北京站建国门 朝阳门 东四十条 东直门[2]

如果终点改成“圆明园”,需要通过2号线中转,结果如下:

[1]王府井 天安门东 天安门西 西单 复兴门 [1][2]阜成门 车公庄 西直门 [2][3]动物园 国家图书馆 魏公村 人民大学 海淀黄庄 中关村 北京大学东门 圆明园 [3]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丁亚涛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值