8-1 地铁售票查询系统 (100 分)
问题描述
杭州地铁(Hangzhou Metro)是浙江省杭州市及杭州都市圈各地区的城市轨道交通,其首条线路杭州地铁1号线于2012年11月24日正式开通,使杭州成为华东地区第四个、浙江省首个开通地铁的城市。
截至2021年9月,杭州地铁运营线路共9条,分别为杭州地铁1号线、杭州地铁2号线、杭州地铁4号线、杭州地铁5号线、杭州地铁6号线(含杭富段)、杭州地铁7号线、杭州地铁8号线、杭州地铁9号线、杭州地铁16号线,共设车站180座(换乘站不重复统计),换乘车站27座。运营里程共计约332千米(不含2条市域线)。杭州都市圈轨道交通线网总里程约400千米。
截至2018年9月,杭州市城市轨道交通线网规划总里程539公里, 其中地铁三期建设规划总里程为387.8公里。2022年杭州亚运会前,杭州将形成“11条轨道线+2条市域线”共计13条线路,总长度达516公里的城市轨道交通骨干网络,实现十城区全覆盖。
本大作业要求设计一个地铁售票查询系统,输入起点站名和终点站名,请输出乘坐地铁线路(如有多条,请显示全部的乘车线路)以及费用(最小费用)。
注:
1、为简化票价计算,设定地铁票价按乘坐站数计算;3站(含)内2元,4-6站(含) 3元,7-11站(含) 4元,12-16站(含)5元; 17站(含)以上部分,每增加1元可乘坐5站;
2、起点站和终点站可能在同一线路上,也可能不在同一线路上(需要换乘,复杂的情况可能需要多次换乘);
3、乘坐地铁可能有多种情况,计算费用可能也会不同,请输出最小费用。例如:从建国北路站到三坝站既可以乘坐5号线,也可以乘坐2号线,由于乘坐站数不一样,产生的费用也不一样,请输出最低费用。
4、本系统只需要考虑杭州地铁的1、2、4、5这四条线路,这四条线路的站点都已经按序列出。
5、地铁线路已有指导的文件给出,系统应该从指定的文件中导出线路和地铁站名。
一波潦草的问题分析
基本思路:首先将问题分类,分别是三种情况:错误输入,不换车和换车。
如果起点终点可以在一条线上实现,则不换车,方向为起点→终点;
如果不能在一条线上完成,又已知四条地铁线两两之间都联通,即最多一次换乘必定可以达到目的,则问题转化为寻找连接两条地铁线的中转站点。这里我们可以先用一个数组保存所有可换乘站点名,然后逐个搜索,接通则输出就可以了(我们是要求输入所有方案的)。
最后,如果方案不止一种,还要输出最小费用。
废话不多说先放代码:
#include<stdio.h>
#include<string.h>
char a[20],b[20],name[20];
int i,j,w,k,t,fi,fj;
int fa[6]={-1,-1,-1,-1,-1,-1},fb[6]={-1,-1,-1,-1,-1,-1};//记录输入站点位置
int line[6]={0},count[5]={0};
static int x[6][38];
char s[6][38][20]={
{""},
{
"湘湖站",
"滨康路站",
"西兴站",
"滨和路站",
"江陵路站",
"近江站",
"婺江路站",
"城站站",
"定安路站",
"龙翔桥站",
"凤起路站",
"武林广场站",
"西湖文化广场站",
"打铁关站",
"闸弄口站",
"火车东站站",
"彭埠站",
"七堡站",
"九和路站",
"九堡站",
"客运中心站",
"下沙西站",
"金沙湖站",
"高沙路站",
"文泽路站",
"文海南路站",
"云水站",
"下沙江滨站",
"杭州大会展中心站",
"港城大道站",
"南阳站",
"向阳路站",
"萧山国际机场站"},
{
"朝阳站",
"曹家桥站",
"潘水站",
"人民路站",
"杭发厂站",
"人民广场站",
"建设一路站",
"建设三路站",
"振宁路站",
"飞虹路站",
"盈丰路站",
"钱江世纪城站",
"钱江路站",
"庆春广场站",
"庆菱路站",
"建国北路站",
"中河北路站",
"凤起路站",
"武林门站",
"沈塘桥站",
"下宁桥站",
"学院路站",
"古翠路站",
"丰潭路站",
"文新站",
"三坝站",
"虾龙圩站",
"三墩站",
"墩祥街站",
"金家渡站",
"白洋站",
"杜甫村站",
"良渚站"},
{""},
{
"池华街站",
"金家渡站",
"好运街站",
"杭行路站",
"储运路站",
"平安桥站",
"独城生态公园站",
"吴家角港站",
"桃源街站",
"皋亭坝站",
"新天地街站",
"华中南路站",
"笕桥老街站",
"黎明站",
"明石路站",
"彭埠站",
"火车东站站",
"新风站",
"新塘站",
"景芳站",
"钱江路站",
"江锦路站",
"市民中心站",
"城星路站",
"近江站",
"甬江路站",
"南星桥站",
"复兴路站",
"水澄桥站",
"联庄站",
"中医药大学站",
"杨家墩站",
"浦沿站"},
{
"金星站",
"绿汀路站",
"葛巷站",
"创景路站",
"良睦路站",
"杭师大仓前站",
"永福站",
"五常站",
"蒋村站",
"浙大紫金港站",
"三坝站",
"萍水街站",
"和睦站",
"大运河站",
"拱宸桥东站",
"善贤站",
"西文街站",
"香积寺路站",
"杭氧站",
"打铁关站",
"建国北路站",
"万安桥站",
"城站站",
"江城路站",
"候潮门站",
"南星桥站",
"长河站",
"聚才路站",
"江晖路站",
"滨康路站",
"博奥路站",
"金鸡路站",
"人民广场站",
"育才北路站",
"通惠中路站",
"火车南站站",
"双桥站",
"姑娘桥站"}
};
void begin(){
x[1][1]=1;x[5][29]=1;
x[1][5]=2;x[4][24]=2;
x[1][7]=3;x[5][22]=3;
x[1][10]=4;x[2][17]=4;
x[1][13]=5;x[5][19]=5;
x[1][15]=6;x[4][16]=6;
x[1][16]=7;x[4][15]=7;
x[2][5]=8;x[5][32]=8;
x[2][12]=9;x[4][20]=9;
x[2][15]=10;x[5][20]=10;
x[2][25]=11;x[5][10]=11;
x[2][29]=12;x[4][1]=12;
x[4][26]=13;x[5][25]=13;
}//标出所有可换乘站点
void direction(int x,int y){
if(!x)
switch(y){
case 1:strcpy(name,"萧山国际机场方向");break;
case 2:strcpy(name,"良渚方向");break;
case 4:strcpy(name,"浦沿方向");break;
case 5:strcpy(name,"姑娘桥方向");break;
}
else switch(y){
case 1:strcpy(name,"湘湖方向");break;
case 2:strcpy(name,"朝阳方向");break;
case 4:strcpy(name,"池华街方向");break;
case 5:strcpy(name,"金星方向");break;
}
}//确定地铁乘坐方向
int max(int x,int y){
return (x>y)?1:0;
}
int money(int n){
if(n<=3)return 2;
else if(n<=6)return 3;
else if(n<=11)return 4;
else if(n<=16)return 5;
else return 5+(n-16)/5+1;
}//输入站数,输出费用
int check(char a[],char b[]){
int k1=0,k2=0;
for(i=0;i<6;i++){
for(j=0;j<38;j++)
{
if(strcmp(a,s[i][j])==0)
{
if(k1!=2)k1=1;
fa[i]=j;
for(w=0;w<38;w++){
if(strcmp(b,s[i][w])==0){
if(w==j){//若输入两个站点相同也默认为输入了错误的站点名
k1=0;
break;
}
else
{
k1=2;
fb[i]=w;
line[i]=1;
break;
}
}
}
}
if(strcmp(b,s[i][j])==0){
k2=1;
fb[i]=j;
}
}//记录两个站点的位置用于后续搜索。
}//判断输入的两个站点是否需要换乘,需要则返回1,不需要则返回2,查无此站点返回0
if(k1==2) return 2;
else if(k1==1&&k2==1) return 1;
else return 0;
}
int find(int fi,int fj){
t=0;
for(i=0;i<38;i++){
for(j=0;j<38;j++){
if(x[fi][i]==x[fj][j]&&x[fi][i]!=0&&x[fj][j]!=0){
direction(max(fa[fi],i),fi);
printf("乘坐%d号线 (%s),\n",fi,name);
if(i>fa[fi]){
for(w=fa[fi];w<=i;w++){
if(w==fa[fi])printf("上车 :%s ,途经 :",s[fi][w]);
else if(w==i)printf(" 下车 :%s。",s[fi][w]);
else printf(" %s,",s[fi][w]);
count[t]++;
}
}//往后坐
else {
for(w=fa[fi];w>=i;w--){
if(w==fa[fi])printf("上车 :%s ,途经 :",s[fi][w]);
else if(w==i)printf(" 下车 :%s。",s[fi][w]);
else printf(" %s,",s[fi][w]);
count[t]++;
}
} //往前坐
direction(max(j,fb[fj]),fj);
printf("\n乘坐%d号线 (%s),\n",fj,name);//之后换乘下一条线
if(j<fb[fj]){
for(w=j;w<=fb[fj];w++){
if(w==j)printf("上车 :%s ,途经 :",s[fj][w]);
else if(w==fb[fj])printf(" 下车 :%s。",s[fj][w]);
else printf(" %s,",s[fj][w]);
count[t]++;
}
}//往后坐
else {
for(w=j;w>=fb[fj];w--){
if(w==j)printf("上车 :%s ,途经 :",s[fj][w]);
else if(w==fb[fj])printf(" 下车 :%s。",s[fj][w]);
else printf(" %s,",s[fj][w]);
count[t]++;
}
} //往前坐
printf("费用 :%d元\n",money(count[t]));
t++;
}
}
}
}//主要是换乘的情况
int mincount(){
int m=count[0];
for(i=0;i<t;i++)
if(m>count[i])
m=count[i];
return m;
}//最短路线
int main(){
begin();
gets(a);
gets(b);
if(check(a,b)==0)printf("错误的站点名\n");
else if(check(a,b)==1) {
//printf("换车\n");
for(i=0;i<6;i++){
if(fa[i]!=-1){
fi=i;
for(j=0;j<6;j++)if(fb[j]!=-1)fj=j;
find(fi,fj);
}
}
printf("最低费用 :%d元",money(mincount()));
}
else {
//printf("不换车\n");
t=0;
for(i=0;i<6;i++){
if(line[i]==1){
direction(max(fa[i],fb[i]),i);
printf("乘坐%d号线 (%s),\n",i,name);
if(fa[i]<=fb[i])
for(j=fa[i];j<=fb[i];j++)
{
if(j==fa[i])printf("上车 :%s ,途经 :",s[i][j]);
else if(j==fb[i])printf(" 下车 :%s",s[i][j]);
else printf(" %s,",s[i][j]);
count[t]++;
}
else
for(j=fa[i];j>=fb[i];j--){
if(j==fa[i])printf("上车 :%s ,途经 :",s[i][j]);
else if(j==fb[i])printf(" 下车 :%s",s[i][j]);
else printf(" %s,",s[i][j]);
count[t]++;
}
printf("。费用 :%d元\n",money(count[t]));
t++;
}
}
if(t>1)printf("最低费用 :%d元",money(mincount()));
}
}
测试用例
(1) 错误的站点名
1.错误输入:比如不存在的站名,或者不写“站”
文新站
丰潭路
2.起点终点相同输入
沈塘桥站
沈塘桥站
(2)不换车
1.只有一种坐法
三坝站
金家渡站
2.多种坐法
建国北路站
三坝站
(3)换车
1.起点终点都不在换乘点
丰潭路站
市民中心站
2.起点终点有一个在换车点
凤起路站
姑娘桥站
3.起点终点都在换车点
凤起路站
南星桥站
好了,本文到这里就结束了。
( ps:作者是个刚学了一学期c语言的计算机专业的小白,这是我的第一篇文章,写的不好大家多多担待,也欢迎各位路过的大佬批评指正)