有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]