由于这里只考虑杭州1、2、4、5四条线路
然后我们发现从任意线路都可以转乘到其他3条线路
所以问题就简化成:起点(Origion)与终点(Terminal)是否在同一线路
不在同一线路也没关系,
在起点终点之间找transfer( FindTransfer(Line of Origin, Line of Terminal); )来建立两点联系:
=> Origion -> Transfer Transfer -> Terminal 这两段都是可以视作同一线路
核心函数:Travel_inSameLine(StationA, StationB);
别问为什么最近老发大作业,我也不想QAQ
#include
#include
#include
// 拢共四条线路 我们发现从任意线路都可以转乘到其他3条线路 => 最多换乘一次
char Station[6][40][50]={
{""},
{"","湘湖站","滨康路站","西兴站","滨和路站","江陵路站","近江站","婺江路站","城站站","定安路站","龙翔桥站","凤起路站",
"武林广场站","西湖文化广场站","打铁关站","闸弄口站","火车东站站","彭埠站","七堡站","九和路站","九堡站","客运中心站",
"下沙西站","金沙湖站","高沙路站","文泽路站","文海南路站","云水站","下沙江滨站","杭州大会展中心站","港城大道站","南阳站",
"向阳路站","萧山国际机场站"},
{"","朝阳站","曹家桥站","潘水站","人民路站","杭发厂站","人民广场站","建设一路站","建设三路站","振宁路站","飞虹路站","盈丰路站",
"钱江世纪城站","钱江路站","庆春广场站","庆菱路站","建国北路站","中河北路站","凤起路站","武林门站","沈塘桥站","下宁桥站",
"学院路站","古翠路站","丰潭路站","文新站","三坝站","虾龙圩站","三墩站","墩祥街站","金家渡站","白洋站",
"杜甫村站","良渚站"},
{""},
{"","池华街站","金家渡站","好运街站","杭行路站","储运路站","平安桥站","吴家角港站","桃源街站","皋亭坝站","新天地街站",
"华中南路站","笕桥老街站","黎明站","明石路站","彭埠站","火车东站站","新风站","新塘站","景芳站","钱江路站",
"江锦路站","市民中心站","城星路站","近江站","甬江路站","南星桥站","复兴路站","水澄桥站","联庄站","中医药大学站",
"杨家墩站","浦沿站"},
{"","金星站","绿汀路站","葛巷站","创景路站","良睦路站","杭师大仓前站","永福站","五常站","蒋村站","浙大紫金港站","三坝站",
"萍水街站","和睦站","大运河站","拱宸桥东站","善贤站","西文街站","东新园站","杭氧站","打铁关站", "宝善桥站", "建国北路站",
"万安桥站","城站站","江城路站","候潮门站","南星桥站","长河站","聚才路站","江晖路站","滨康路站","博奥路站",
"金鸡路站","人民广场站","育才北路站","通惠中路站","火车南站站","双桥站","姑娘桥站"}
};
char TransferStation[20][50] = {
"滨康路站", "近江站", "城站站", "凤起路站", "打铁关站", "火车东站站","彭埠站", "金家渡站", "三坝站", "建国北路站", "钱江路站",
"人民广场站", "南星桥站"
};
// 功能:想要从A号线转到B号线 我可以去哪些站点转乘
int* getPosition(char *station);
int* getPosition(char *station, int exclusion);
int Travel_inSameLine(int StationA, int StationB, int Line);
bool isSameLine(int *PositionA, int *PositionB);
int CalculateNumber(int *PositionA, int *PositionB);
int CalculateCost(int stationCount);
bool isTransfer(int *position);
bool isTransfer(char *station);
int* FindTransfer(int LineA, int LineB);
int* Transfer(int line, int station);
// 测试案例:
// 凤起路站 朝阳站 (同一条线路)
// 湘湖站 朝阳站 (one way)
// 湘湖站 池华街站 (three ways)
int main() {
char Origin[50];
char Terminal[50];
printf("请输入起点站点名(别忘了最后的“站”字!): ");
scanf("%s", Origin);
getchar();
printf("请输入终点站点名(别忘了最后的“站”字!): ");
scanf("%s",Terminal);
getchar();
int *OriginPosition = getPosition(Origin);
while(OriginPosition == NULL) {
printf("Origin's name is WRONG!\nPlease Input it again!\n\n");
scanf("%s", Origin);
getchar();
OriginPosition = getPosition(Origin);
}
printf("Original Station exists.\n") ;
int *TerminalPosition = getPosition(Terminal);
while(TerminalPosition == NULL) {
printf("Terminal's name is WRONG!\nPlease Input it again!\n\n");
scanf("%s", Origin);
getchar();
TerminalPosition = getPosition(Terminal);
}
printf("Terminal Station exists.\n") ;
// 根据Position数组有效长度判断是否为transfer
// 判断起点终点是否在同一线路
// 不同线路:找Terminal所在的线路上的Transfer, 看哪一个可以转乘到Origin那条线路
int stationCount = CalculateNumber(OriginPosition, TerminalPosition);
int Cost = CalculateCost(stationCount);
printf("\nAll in all, You will pass by %d Stations, and the Minimal Cost is %d CNY", stationCount, Cost);
return 0;
}
// position的第一位存储数组有效长度
int* getPosition(char *station) {
int k = 1;
int *position = (int*)malloc(sizeof(int) * 5);
for(int i = 1; i < 6; i++) {
if(i == 3) continue;
int number = 33;
if(i == 5) number = 38;
for(int j = 1; j < number; j++) {
if(!strcmp(Station[i][j], station)) {
position[k++] = i;
position[k++] = j;
}
if(k == 5) break;
}
if(k == 5) break;
}
position[0] = k;
if(k == 3 || k == 5) return position;
else return NULL;
}
int* getPosition(char *station, int exclusion) {
int k = 1;
int *position = (int*)malloc(sizeof(int) * 5);
for(int i = 1; i < 6; i++) {
if(i == 3) continue;
int number = 33;
if(i == 5) number = 38;
for(int j = 1; j < number; j++) {
if(j == exclusion) continue;
if(!strcmp(Station[i][j], station)) {
position[k++] = i;
position[k++] = j;
}
}
}
position[0] = k;
if(k == 3 || k == 5) return position;
else return NULL;
}
bool isSameLine(int *PositionA, int *PositionB) {
for(int i = 1; i < PositionA[0]; i += 2) {
for(int j = 1; j < PositionB[0]; j += 2) {
if(PositionB[j] == PositionA[i]) return true;
}
}
return false;
}
// A -> B
int CalculateNumber(int *PositionA, int *PositionB) {
int MinCount = INT_MAX;
bool SameLine = false, A_isTransfer = false, B_isTransfer = false, hasTransfer = false;
// 讨论transfer的意义 => 该站点是transfer的话 => 就有两组可转乘站点啦
int Line = 0;
if(PositionA[0] != 3 || PositionB[0] != 3) {
hasTransfer = true;
if(PositionA[0] != 3) A_isTransfer = true;
if(PositionB[0] != 3) B_isTransfer = true;
}
// 判断是否为同一线路
int StationA = PositionA[2], StationB = PositionB[2];
for (int i = 1; i < PositionA[0]; i += 2) {
for (int j = 1; j < PositionB[0]; j += 2) {
if (PositionB[j] == PositionA[i]) {
SameLine = true;
Line = PositionA[i];
StationA = PositionA[i + 1], StationB = PositionB[j + 1];
break;
}
}
if(SameLine) break;
}
if(SameLine) MinCount = Travel_inSameLine(StationA, StationB, Line);
else {
int bestWay = -1;
for (int i = 1; i < PositionA[0]; i += 2) {
for (int j = 1; j < PositionB[0]; j += 2) {
printf("\nNeed to Transfer: From Line%d -> Line%d\n", PositionA[i], PositionB[j]);
int *transfer = FindTransfer(PositionA[i], PositionB[j]);
int wayNumber = transfer[0] / 2;
for(int z = 0; z < wayNumber; z++) {
// 这两个站点都以LineB为基准
// 这里下标是z + z => 规律没找清楚
int transfer_inA = transfer[z*2 + 1], transfer_inB = transfer[z*2 + 2];
printf("\nWay of %d: \n", z + 1);
int count1 = Travel_inSameLine(PositionA[i + 1], transfer_inA, PositionA[i]);
int count2 = Travel_inSameLine(transfer_inB, PositionB[j + 1], PositionB[j]);
// MinCount = MinCount > (count1 + count2) ? (count1 + count2) : MinCount;
int count = count1 + count2;
printf("\n一共需要乘坐%d站\n", count);
if(MinCount > count) {
MinCount = count;
bestWay = z + 1;
}
}
}
}
printf("\nThe Minimal Count way is the Way %d\n", bestWay);
}
return MinCount;
}
int CalculateCost(int stationCount) {
int cost = 0;
if(stationCount <= 3) cost = 2;
else if(stationCount <= 6) cost = 3;
else if(stationCount <= 11) cost = 4;
else cost = 5;
if(stationCount >= 17) {
cost += (stationCount - 16) / 5;
if((stationCount % 5)) cost++;
}
return cost;
}
bool isTransfer(int *position) {
if(position[0] == 3) return false;
else return true;
}
bool isTransfer(char *station) {
for(int i = 0; i < 13; i++) {
if(!strcmp(TransferStation[i], station)) return true;
}
return false;
}
// 设计算法帮我检索在LineA有哪些专程到LineB的站点
int* FindTransfer(int LineA, int LineB) {
int n = 33;
if(LineA == 5) n = 38;
int *transfer = (int*)malloc(sizeof(int));
int k = 1;
for(int i = 1; i < n; i++) {
// 目标得到一个transfer的position然后判断能否到底LineB
int *position = NULL;
if(isTransfer(Station[LineA][i])) position = getPosition(Station[LineA][i]);
else continue;
// 注意:transfer存两个line
int index = LineA < LineB ? 3 : 1;
if(position[index] == LineB) {
transfer[k++] = i; // 奇数位记载LineA上站点位置
transfer[k++] = position[index + 1]; // 偶数位记载LineB上站点位置
}
}
transfer[0] = k;
return transfer;
}
int Travel_inSameLine(int StationA, int StationB, int Line) {
int count = abs(StationA - StationB);
if(!count) return count;
printf("\nIn Line%d: Begin at %s", Line, Station[Line][StationA]);
int format = 1;
if(StationA < StationB) {
for(int i = StationA; i < StationB; i++) {
printf(" -> %s ", Station[Line][i + 1]);
format++;
if(format % 5 == 0) printf("\n");
}
}else if(StationA > StationB) {
for(int i = StationA; i > StationB; i--) {
printf(" -> %s ", Station[Line][i - 1]);
format++;
if(format % 5 == 0) printf("\n");
}
}
printf("\n");
return count;
}