[C语言] 杭州地铁售票查询系统大作业

该程序实现了查询杭州地铁1、2、4、5号线中任意两个站点之间的最短换乘路径和最少费用。通过Travel_inSameLine函数判断同线换乘,FindTransfer找到换乘站,CalculateCost计算费用。主要功能包括获取站点位置、判断是否同线、计算路径数量和成本。测试用例包括同线和不同线的换乘情况。
摘要由CSDN通过智能技术生成

由于这里只考虑杭州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 <stdio.h>
#include <string.h>
#include <stdlib.h>

//  拢共四条线路 我们发现从任意线路都可以转乘到其他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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值