[置顶]C++实现景区信息管理系统

本文介绍了使用C++实现的景区信息管理系统,包括应用菜单、导游线路图的创建和输出、回路检测、景点查找与排序、最短路径计算、道路规划以及车辆进出停车场的管理流程。系统运用了邻接链表、迪杰斯特拉算法等技术,提供了丰富的功能。

景区信息管理系统

实现了:

 

1.1 建立主程序应用菜单选项

主程序应用菜单选项包含所实现的所有功能,并且对选项采用数字标识进行选择,对其他错误输入可以进行判别,提示输入错误。

1.2 导游线路图的创建级景区分布图的输出

用邻接链表存储景点分布图的信息,(带权无向)图的邻接链表。输出景区景点分布图(邻接矩阵)。图中边的权值∞用32767表示。

1.3  输出导游线路图

景区旅游信息管理系统中制订旅游景点导游线路策略,首先通过遍历景点,给出一个入口景点,建立一个导游线路图,导游线路图用有向图表示。

1.4  输出导游线路图中是否有回路

景区旅游信息管理系统中,创建好导游路线图后,判断该图中是否存在回路。

1.5 查找及排序

l  查找功能: 可以根据用户输入的关键字进行景点的查找,关键字可以在景点名称也可以在景点介绍中。查找成功则返回景点的相关简介,如果查找不成功请给予正确提示。

l  排序功能:按景点欢迎度,景点的岔路数对景点进行排序并打印出来排序顺序。

1.6  输出两个景点之间最短路径和最短距离

求出两个景点间的最短路径和最短距离,并且输出道路修建规划图。 算法采用迪杰斯特拉算法。

1.7   输出道路修建规划图

道路建设首先要保证能连通所有景点,但又要花最小的代价。

1.8  输出车辆的进出信息

1.8.1 具体需求:

停车场是一个可以停放n辆汽车,且只有一个大门可供汽车进出。汽车在停车场内按车辆到达时间的先后顺序,依次排列,若车场内已停满n辆车,后来的车只能在门外的便道上等候,一旦有车开走,则排在便道上的第一辆车即可开入;当停车场内某辆车要离开时,在它之后进入的车辆必须先退出车场为它让路,待该辆车开出大门外,其它车辆再按原次序进入车场,每辆停放在车场的车在它离开停车场时必须按它停留的时间长短交纳费用。输出每辆车到达后的停车位置(停车场或便道上),以及某辆车离开停车场时应缴纳的费用和它在停车场内停留的时间。

1.8.2  停车场的管理流程如下:

A.当车辆要进入停车场时,检查停车场是否已满,如果未满则车辆进入停车场;如果停车场已满,则车辆进入便道等候。

B.当车辆要求出栈时,先让在它之后进入停车场的车辆退出停车场为它让路,再让该车退出停车场,让路的所有车辆再按其原来进入停车场的次序进入停车场。之后,再检查在便道上是否有车等候,有车则让最先等待的那辆车进入停车场。

1.8.3 车辆出入清单:

每一组输入数据包括三个数据项:汽车“到达”或“离去”信息、汽车牌照号码以及到达或离去的时刻。对每一组输入数据进行操作后的输出信息为:若是车辆到达,则输出汽车在停车场内或便道上的停车位置;若是车辆离去,则输出汽车在停车场内停留的时间和应交纳的费用(在便道上停留的时间不收费)。

1.9

退出整个程序。

 

完整代码如下(直接编译可运行):

 

#include <iostream>
#include <fstream>
#include <time.h> 
#include <stdio.h>
#include <cstring>
#include <iomanip>
#include <stack>
#include <queue>
#define MAX 20
#define MAX2 2
#define INFINITY 32767
int arr1[MAX][MAX];

using namespace std;
double arr[MAX][MAX];

class ArcNode {
    public:
        int adjvex;
        ArcNode *nextarc;
        double weight;
};


class VNode {
    public:
        string data1;
        string data2;
        int wel;
        bool wc;
        bool rest; 
        ArcNode *firstarc;
};

class ALGraph {
    public:
        VNode *vertices;
        int vexnum, arcnum;
        ArcNode *arcNode;
};

class zanlind
{
public:
    int number;
    int hour;
    int minute;
};


int LocateVex(ALGraph G, string v) {
    int i; 
    for(i = 0; v != G.vertices[i].data1 && i < G.vexnum; i++)
        ;
    if(i >= G.vexnum)
        return -1;
    return i;
}

int LocateW(ALGraph G, int wel) {
    int i;
    for(i = 0; wel != G.vertices[i].wel && i < G.vexnum; i++)
        ;
    if(i >= G.vexnum)
        return -1;
    return i;
}

void CreateUDN(ALGraph &G) {
    G.arcNode=new ArcNode[MAX];
    G.vertices=new VNode[MAX];
    
    fstream file("info.txt");
    if(file.fail())
    {
        cout << "error open!" << endl;
    }
    int  j;
    ArcNode *s, *t;
    cout<<"请输入顶点数和边数:";
    cin>>G.vexnum>>G.arcnum;
    int i=0;
    cout<<endl;
    while(!file.eof()) 
    {
        file >>G.vertices[i].data1>>G.vertices[i].data2 >> 
        G.vertices[i].wel>> G.vertices[i].rest>>G.vertices[i].wc;
        G.vertices[i].firstarc = NULL;
        i++;
    }    
    cout<<endl;    
    fstream file1("edge.txt");
    if(file.fail())
    {
        cout << "error open!" << endl;
    }
    while(!file1.eof()) 
    {
        int weight;
        string v1, v2;
        file1>>v1>>v2>>weight;
        
        int i = LocateVex(G, v1);
        int j = LocateVex(G, v2);

        s = new ArcNode();
        t = new ArcNode();

        s->adjvex = j;
        s->nextarc = G.vertices[i].firstarc;
        s->weight=weight;
        G.vertices[i].firstarc =s;

        t->adjvex = i;
        t->nextarc = G.vertices[j].firstarc;
        t->weight=weight;
        G.vertices[j].firstarc =t;
    }
    file1.close();
    file.close(); 

}


void  PrintAdjList(ALGraph &G) {
    cout<<"下面是图的邻接链表输出:" <<endl;
    ArcNode *p;
    cout<<"  编号 "<<"顶点"<<"   相邻边编号"<<endl;
    for(int i = 0; i < G.vexnum; i++) {
        cout<<"   "<<i<<"    "<<G.vertices[i].data1;
        for(p = G.vertices[i].firstarc; p; p = p->nextarc)
            cout<<"--------->"<<p->adjvex;
        cout<<endl;
    }


}

void OutputGraph(ALGraph G) {
    cout<<"下面是图的邻接矩阵输出:"<<endl;
    int m1=G.vexnum;
    int m2=G.vexnum;

    for(int i=0; i<m1; i++) {
        for(int j=0; j<m2; j++) {
            arr[i][j]=32767;
        }
    }

    for(int k=0; k<m1; k++) {
        ArcNode *p=G.vertices[k].firstarc;
        for(int i2=0; i2<m2; i2++) {
            if(k==i2) {
                arr[k][i2]=0;
            }
            if(p) {
                arr[k][p->adjvex]=p->weight;
                p=p->nextarc;
            }

        }
    }
    cout<<"        ";
    for(int n1=0; n1<m1; n1++) {
        cout<<setiosflags(ios::left)<<setw(11)<<G.vertices[n1].data1;

    }
    cout<<endl;
    for(int n2=0; n2<m1; n2++) {
        cout<<setiosflags(ios::left)<<setw(10)<<G.vertices[n2].data1;
        for(int n3=0; n3<m1; n3++) {
            cout<<setiosflags(ios::left)<<setw(10)<<arr[n2][n3];

        }
        cout<<endl;


    }


}

bool visited[MAX];
stack<int> *s=new stack<int>();

bool isOver(ALGraph G,bool a[MAX]) {
    for(int i=0; i<G.vexnum; i++) {
        if(a[i]!=1) {
            return false;
        }
    }
    return true;


}

void DFSTraverse(ALGraph G)
{
    bool sta[20];
    int v;
    for (v = 0; v<G.vexnum; v++)
    {
        sta[v] =true;
    }
     stack<int>status;
     int n=0;
     int num = -1;
     int pk;
     ArcNode *e;
     cout << G.vertices[0].data1 << "->";
     sta[0] =false;
     status.push(0);
     int aa, bb;
     aa = 0;

     while (n < G.vexnum-1){
         e = NULL;
         num = status.top();
         e = G.vertices[num].firstarc;
         while (e){
             if (sta[e->adjvex] == false){
                 e = e->nextarc;
             }
             else{
                 status.push(e->adjvex);
                 cout << G.vertices[e->adjvex].data1<<"->";
                 aa = e->adjvex;
                 sta[e->adjvex] = false;
                 n++;
                 break;
             }
                 }
         if (e == NULL){
             pk = status.top();
             bb = pk;
             if (aa != bb){
                 cout << G.vertices[pk].data1<<"->";
             }
            
             status.pop();
         }
         if (status.top() == 0){
             cout << G.vertices[0].data1 << "->";
         }
     }
     cout << endl;
}

bool IsEdge(ALGraph G) {
    string s1, s2;
    cin>>s1>>s2;
    int iA=LocateVex(G,s1);
    int jA=LocateVex(G,s2);

    ArcNode *p=G.vertices[iA].firstarc;
    while(p) {
        if(p->adjvex==jA) {
            return 1;
        } else {
            p=p->nextarc;
        }
    }
    return 0;


}

int adjlist[MAX];
void FindInDegree( ALGraph &g) {
    int i;
    ArcNode *p;
    for (i=0; i<g.vexnum; i++)
        adjlist[i]=0;
    for (i=0; i<g.vexnum; i++) {
        p=g.vertices[i].firstarc;
        while(p) {
            adjlist[p->adjvex]++;
            p=p->nextarc;
        }
    }
}
void JudgeCir(ALGraph G) {
    FindInDegree(G);
    int count=0;
    int Q[MAX];
    int front,rear,v;
    front=rear=-1;
    for(int i=0; i<G.vexnum; i++) {
        if((adjlist[i]==0)||(adjlist[i]==1)) {
            Q[++rear]=i;
            count++;
        }
    }

    while(front!=rear) {
        v=Q[++front];
        if(adjlist[v]==1) {
            adjlist[v]=-1;
            for(int j=0; j<G.vexnum; j++) {
                if(arr[v][j]>0 && arr[v][j]<32767) {
                    adjlist[j]--;
                    if(adjlist[j]==1) {
                        Q[++rear]=j;
                        count++;
                    }
                }
            }
        } else {
            adjlist[v]=-1;
        }
    }

    if(count<G.vexnum) {
        cout<<"图中有回路"<<endl;
    } else
        cout<<"图中无回路"<<endl;
}

int in[MAX];

void LocateVex2(ALGraph G, string v) {
    for(int i = 0;i < MAX; i++)
    {
        in[i]=10000;
    }
    for(int i = 0;i < G.vexnum; i++)
    {
        if(G.vertices[i].data1.find(v)<G.vertices[i].data1.length() ||
        G.vertices[i].data2.find(v)<G.vertices[i].data2.length())    
        {
            in[i]=i;
        }
    } 
}

void Search(ALGraph G,string s) {
    FindInDegree(G);
    LocateVex2(G, s);
    for(int i=0;i<G.vexnum;i++)
    {
        if(in[i]!=10000)
        {
            cout<<"您所要查询的景点介绍为:"<<endl
                <<endl<<"该景点名字是:"
                <<G.vertices[in[i]].data1
                <<" "<<endl
                <<"该景点介绍为:"<<G.vertices[in[i]].data2<<endl
                <<"该景点欢迎度为:"
                <<G.vertices[in[i]].wel<<endl<<"有无休息区为:"
                <<G.vertices[in[i]].rest
                <<endl<<"有无厕所为:"<<G.vertices[in[i]].wc
                <<endl<<endl;
        }

    }

}

void SortWel(ALGraph G) {
    int ary[G.vexnum];

    for(int i=0; i<G.vexnum; i++) {
        ary[i]=G.vertices[i].wel;
    }

    int i, j, tmp;
    for(i=0; i<G.vexnum; i++) {
        tmp = ary[i];
        for(j=G.vexnum-1; j>i; j--) {
            if(tmp < ary[j]) {
                ary[i] = ary[j];
                ary[j] = tmp;
                tmp = ary[i];
            }
        }
    }

    for(int j=0; j<G.vexnum; j++) {
        int m=LocateW(G,ary[j]);
        cout<<j+1<<"、 "<<G.vertices[m].data1<<endl;
    }
}

bool isInN(ALGraph G,int a[MAX],int n)
{
    for(int i=0;i<G.vexnum;i++)
    {
        if(a[i]==n)
        {
            return true;
        }
    }
    return false;
}

void SortN(ALGraph G) {
    int ary[G.vexnum];
    int a[G.vexnum];

    for(int j=0; j<G.vexnum; j++) {
        a[j]=10000;
    }
    
    FindInDegree(G);
    for(int i=0; i<G.vexnum; i++) {
        ary[i]=adjlist[i];
    }
    
    int i, j, tmp;
    for(i=0; i<G.vexnum; i++) {
        tmp = ary[i];
        
        for(j=G.vexnum-1; j>i; j--) {
            if(tmp <= ary[j]) {
                a[i]=j;
                ary[i] = ary[j];
                a[i]=j;
                ary[j] = tmp;
                tmp = ary[i];
            }    
            
            
        }
    }

    for(int j=0;j<G.vexnum;j++)
    {
        for(int i=0;i<G.vexnum;i++)
        {
            if(ary[j]==adjlist[i])
            {
                if(!isInN(G,a,i))
                {
                    a[j]=i;
                }
                else
                {
                    continue;
                }
            }
        }
    }    
        for(int i=0;i<G.vexnum;i++)
    {
        cout<<i+1<<"、"<<G.vertices[a[i]].data1<<endl;
    }


}

void ShortestPath_DIJ(ALGraph G,int v0, int p[][MAX], int D[]) {
    int v, w, i, j, min;
    bool final[10];
    for(v=0; v<G.vexnum; v++) {
        final[v]=false;
        D[v]=arr[v0][v];
        for(w=0; w<G.vexnum; w++)
            p[v][w]=-1;
        if(D[v]<INFINITY) {
            p[v][0]=v0;
            p[v][1]=v;
        }
    }

    D[v0]=0;
    final[v0]=true;

    for(i=1; i<G.vexnum; i++) {
        min=INFINITY;
        for(w=0; w<G.vexnum; w++)
            if(!final[w] && D[w]<min) {
                v=w;
                min=D[w];
            }
        final[v]=true;
        for(w=0; w<G.vexnum; w++) {
            if(!final[w] && min<INFINITY && arr[v][w]<INFINITY
             && (min+arr[v][w]<D[w])) {
                D[w]=min+arr[v][w];
                for(j=0; j<G.vexnum; j++) {
                    p[w][j]=p[v][j];
                    if(p[w][j]==-1) {
                        p[w][j]=w;
                        break;
                    }
                }

            }
        }
    }
}

bool isInVe(ALGraph G,string va)
{
    for(int i=0;i<G.vexnum;i++)
    {
        if(G.vertices[i].data1==va)
        {
            return true;
        }
    }
    return false;
}

void printShortestPath(ALGraph G)
{
    
    int iA,jA;
    string s1,s2;
    int p[MAX][MAX];
    int D[MAX];
    cout<<"请输入要查询距离的两个景点的名称:";
    cin>>s1>>s2;
    if(isInVe(G,s1) && isInVe(G,s2))
    {
        iA=LocateVex(G,s1);
        jA=LocateVex(G,s2);
        ShortestPath_DIJ(G,iA, p, D);
        cout<<"到各顶点的最短路径及长度为:"<<endl;
        
        if(jA!=0 && D[jA]!=INFINITY) {
            cout<<"最短路径为:";
            for(int j=0; j<G.vexnum; j++) {
                if(p[jA][j]>-1)
                    cout<<G.vertices[p[jA][j]].data1
                        <<" ";
                }
                cout<<endl;
                cout<<"最短距离为:"<<D[jA];
        } else if(D[jA]==INFINITY)
                    cout<<G.vertices[iA].data1<<"-"
                    <<G.vertices[jA].data1
                    <<":"<<"不可达"<<endl;    
    }
    else
    {
        cout<<"您输入的景点名称不存在,请输入正确的景点名称:"<<endl;
        printShortestPath(G);
    }

 } 
 
void prim(ALGraph G,int v,double arr[MAX][MAX]) {

    int lowcost[MAX];
    int min;
    int closest[MAX],i,j,k;
    for(i=0; i<G.vexnum; i++) {
        lowcost[i]=arr[v][i];
        closest[i]=v;
    }
    for(i=1; i<G.vexnum; i++) {
        min=INFINITY;
        for(j=0; j<G.vexnum; j++) {
            if(lowcost[j]!=0&&lowcost[j]<min) {
                min=lowcost[j];
                k=j;
            }
        }
        cout<<"从"<<G.vertices[closest[k]].data1<<"到"
        <<G.vertices[k].data1<<"修一条路"<<endl;
        lowcost[k]=0;

        for(j=0; j<G.vexnum; j++) {
            if(arr[k][j]!=0 && arr[k][j]<lowcost[j]) {
                lowcost[j]=arr[k][j];
                closest[j]=k;
            }
        }

    }
}   
   
stack<zanlind> parking;  
stack<zanlind> cars;  
queue<zanlind> waits;
int z[MAX2];
bool isInZan(int zan[],int number)
{
    for(int i=0;i<MAX2;i++)
    {
        if(zan[i]==number)
        {
            return true;
        }
    }
    return false;
}

int indexZ(int z[],int n)
{
    for(int i=0;i<MAX2;i++)
    {
        if(z[i]==n)
        {
            return i;
        }
    }
    return -1;
}
void goIn()
{
    int k1=0;
    zanlind zan;
    cout<<"车牌号为:";
    cin>>zan.number;
    cout<<endl;
    /*
    time_t t = time(0);
    char tmp[64]; 
    strftime(tmp,sizeof(tmp),"%X ",localtime(&t));
    zan.time=tmp;
    */
    struct tm *newtime;
    time_t long_time;
    time( &long_time ); //Get time as long integer
    newtime = localtime( &long_time ); 
    int h = newtime->tm_hour;//得到当前时间的小时
    int m = newtime->tm_min;//得到当前时间的分钟
    zan.hour=h;
    zan.minute=m;
    
    
    cout<<"进场时间为:";
    if(zan.minute>=1 && zan.minute<10)
    {
        cout<<zan.hour<<":0"<<zan.minute<<endl;
    }
    else
    {
        cout<<zan.hour<<":"<<zan.minute<<endl;
    }
    
    
    if(parking.size()<MAX2)
    {
        for(int m=0;m<MAX2;m++)
        {
            if(z[m]==0)
            {
                z[m]=zan.number;
                break;
            }
        }
        parking.push(zan);
        cout<<"该车已进入停车场在: "<<k1++<<"号车道";    
    }
    else
    {
        cout<<"停车场已满,请等待其他车辆离开:"; 
        waits.push(zan);
    }
}

void goOut()
{
    if(parking.size()<=0)
    {
        cout<<"停车场为空,没有车要离开!";
    }
    else 
    {
        cout<<"请输入您的车牌号:";
        int number;
        cin>>number;
        if(isInZan(z,number))
        {
            while(parking.top().number!=number)
            {
                cars.push(parking.top());
                parking.pop();
            }
            
            int num=indexZ(z,parking.top().number);
            z[num]=0;
            /*
            time_t t = time(0);
              char tmp[64]; 
              strftime(tmp,sizeof(tmp),"%X ",localtime(&t));
              */
              struct tm *newtime;
            time_t long_time;
            time( &long_time ); //Get time as long integer
            newtime = localtime( &long_time ); 
            int h = newtime->tm_hour;//得到当前时间的小时
            int m = newtime->tm_min;//得到当前时间的分钟
              cout<<"车牌号为:"<<parking.top().number<<"的车要离开了"<<endl
              <<"停车时间为: "
              <<(h*60+m)-(parking.top().hour*60+parking.top().minute)<<"分钟"<<endl
              <<"停车费用为:"
              <<((h*60+m)-(parking.top().hour*60+parking.top().minute))*5<<"元"<<endl; 
                  parking.pop();
              
              while(!cars.empty()) 
              {
                  parking.push(cars.top());
                cars.pop();    
            }
            
            while(parking.size()<MAX2)
            {
                if(waits.size()!=0)
                {    
                    for(int m=0;m<MAX2;m++)
                    {
                        if(z[m]==0)
                        {
                            z[num]=waits.front().number;
                        }
                    }
                    parking.push(waits.front());        
                    waits.pop();
                }
                else
                {
                    break;
                }

            } 
        }    
        
        else
        {
            cout<<"没有该辆车!请输入正确的车牌号:"<<endl;    
        }                
        
    }
        
}

void parkinglot()
{
    r2:
        cout<<endl<<"            **停车场管理程序**          "<<endl
        <<"--------------------------------------------------"<<endl
        <<"**"
        <<"** A---汽车进车场  D---汽车出车场  E---退出程序 **"<<endl 
        <<"--------------------------------------------------"<<endl
        <<"请选择:<A ,D ,E>:";
        char choose;
        cin>>choose;
        if(choose=='A' || choose=='D' || choose=='E')
        {
            switch(choose)
            {
                case 'A':
                    goIn(); 
                    goto r2;
                case 'D':
                    goOut();
                    goto r2;
                case 'E':
                    break;
                }
        }
        else
        {
            cout<<"您的输入有误,请输入  <A D E>  其中的一项。";
            goto r2;
        }
}

int main() {
    int i, j;
    int iAA;
    ALGraph *G=new ALGraph();
    int choose=0;
    cout<<endl;
    
    while(true) {
r:
        cout<<"------------------------------------------"<<endl
            <<"          欢迎使用景区信息管理系统        "<<endl
            <<"              ***请选择菜单***            "<<endl
            <<"------------------------------------------"<<endl
            <<"   1、创建景区景点分布图                  "<<endl
            <<"   2、输出景区景点分布图                  "<<endl
            <<"   3、输出导游线路图                      "<<endl
            <<"   4、输出导游线路图的回路                "<<endl
            <<"   5、查找及排序                          "<<endl
            <<"   6、求两个景点间的最短路径和最短距离    "<<endl
            <<"   7、输出道路修建规划图                  "<<endl
            <<"   8、停车场车辆进出记录信息              "<<endl
            <<"   0、退出系统                            "<<endl
            <<"请输入您要选择的菜单项: ";
            
        cin>>choose;
        
        if(choose<=8 && choose>=0) {
            if(choose>1 && G->vexnum==0 &&choose!=8) {
                cout<<endl<<"************您的图为空,请先创建您的图**********:"
                <<endl<<endl;
                goto r;
            } else {
                switch(choose) {

                    case 1:
                        CreateUDN(*G);

                        break;
                    case 2:
                        PrintAdjList(*G);
                        cout<<endl;
                        OutputGraph(*G);
                        break;
                    case 3:
                        cout<<"导游路线为:";
                        //CreatTourSortGraph(*G);
                        //DFSTraverse(*G);
                        break;
                    case 4:
                        JudgeCir(*G);
                        break;
                    case 5:
                        
                    while(true)
                    {
                        int ch;
                        cout<<"您需要"
                            <<"  查找(0),"
                            <<"按欢迎度排序(1),"
                            <<"按景点岔路数排序(2),"
                            <<"退出此目录(3) :" ;
                        cin>>ch;
                        string sA;
                        switch(ch)
                        {
                            case 0:
                                cout<<"请输入您要查找的有关景点的关键字:" ;
                                cin>>sA;
                                Search(*G,sA);
                                break;
                            case 1:
                                SortWel(*G);
                                break;
                            case 2:
                                SortN(*G);
                                break;
                            case 3:
                                goto r;
                            default :
                                cout<<"您的输入有误,请重新输入:"<<endl;
                        }
                    }
                    case 6:    
                        printShortestPath(*G);
                        break;
                    case 7:
                        prim(*G,0,arr);
                        break;
                    case 8:
                        parkinglot();
                        break;
                    case 0:
                        exit(0);
                }

            }
            cout<<endl;
        }
        else {
            cout<<"您的输入有误,请重新输入0-8之间的数字"<<endl;

        }


    }
    return 0;
}

所需要的两个edge.txt和info.txt文件。(很重要、一定要有!!!)

 

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值