Dijkstra—校园景点游览问题

#include<iostream>
#include<cstdio>
#include<cstring>
#define MAX 9999999
using namespace std;
typedef struct ArcCell{
    int length;//两点间的距离 
}ArcCell, AdjMatrix[100][100];
//景点 
typedef struct {
    char sce_name[30];//景点名称
    int sce_num;//景点代号
    char sce_intro[200];//景点简介
}Scenery;
//图的数组表示法
typedef struct {
    Scenery vexs[100];
    AdjMatrix arcs;
    int vexnum,arcnum;
}MGraph; 
//全局变量 
int Path[100];//记录最短路径上的节点 
int D[100];//记录节点到起始节点的距离 
bool final[100];//标记该节点是否在路径上 
//由风景名称获取风景在数组中的下标
int GetSce(char sce_name[],MGraph G){ 
    int i;
    for(i=1;i<=G.vexnum;i++)
        if(strcmp(sce_name,G.vexs[i].sce_name)==0)return i;
    return -1;
}
//创建一个图 
void Creat_Graph(MGraph &G){
    int i,j;
    int n1,n2,weight; //起始下标、终止下标、权值 
    char start[30], end[30];
    printf("■请输入景点个数: ");
    scanf("%d",&G.vexnum);//景点个数 
    printf("■请输入路的条数: ");
    scanf("%d",&G.arcnum);//路的条数 
    printf("\n■输入景点信息(名称(char)、代号(int)、简介(char)). \n");
    for(i=1;i<=G.vexnum;i++){
        printf("第 %d 个景点: ",i);
        scanf("%s",G.vexs[i].sce_name);
        scanf("%d",&G.vexs[i].sce_num);
        scanf("%s",G.vexs[i].sce_intro);
    }
    printf("\n■输入路况: \n");
    //先把二维数组给填一下 (相当于vexnum阶矩阵) 
    for(i=1;i<=G.vexnum;i++){
        for(j=1;j<=G.vexnum;j++){
            G.arcs[i][j].length = MAX;
        }
    }
    
    for(i=1;i<=G.arcnum;i++){
        printf("■弧头 & 弧尾 & 权值: ");
        scanf("%s",start);
        scanf("%s",end);
        n1 = GetSce(start,G);//经上面的景点信息获取景点的下标 
        n2 = GetSce(end,G);
        scanf("%d",&weight);
        G.arcs[n1][n2].length = weight;//矩阵双向的权值 
        G.arcs[n2][n1].length = weight;
    }
    printf("OK! 信息录入完毕!\n\n");
}
//输出最短路径 
void OutPutPath(MGraph G,bool find,int sn,int en){
    int i;
    int path[100];
    if(!find){
        printf("Sorry,无法找到从%s到%s的路.\n\n",G.vexs[sn].sce_name,G.vexs[en].sce_name);
        return;
    }
    else {
        printf("\n■■■%s 到 %s 最短路径上依次为: ",G.vexs[sn].sce_name,G.vexs[en].sce_name);
        path[0] = en;
        int k = 1,x = Path[en];
        while(x != sn){
            path[k++] = x;
            x = Path[x];
        }
        path[k] = sn;
        for(i=k;i>=0;i--){
            printf("%s",G.vexs[path[i]].sce_name);
            if(i!=0){
                printf("");
            }
        }
        printf("\n■■■其最短路径长度为: %d\n",D[en]);
        printf("\n");
    }
}
//迪杰斯特拉算法求最短路径 
void Dijkstra(MGraph G,int sn,int en){
    int i;
    int v, min;//v--点的下标,min--节点离起始的距离 
    for(i=1; i<=G.vexnum; i++){
        final[i] = false;//用于记录是否在已确定的点的集合中 
        D[i] = G.arcs[sn][i].length;//每个点与起点的距离 
        //初始化记录最短路径的数组 
        if(D[i]!= MAX)//与起点相连 
            Path[i] = sn; 
        else//不与起点相连 
            Path[i] = 0;
    }
    D[sn] = 0;//初始化最开始的距离0 
    final[sn] = true;//起始节点在路径上 
    Path[sn] = sn;//记录最短路径上的第一个节点 
    bool find = false;//判断是否找到从起点到终点的路 
    while(1){
        min = MAX;
        v = -1;//先默认一个不存在的下标,下面根据各步的比较把最近点的下标赋给v 
        for(i = 1; i <= G.vexnum; i++){//找到当前位置与起点最近的点 
            if(final[i]==false && D[i] < min){//剩下的Ian还没连到最短路径上,而且点和最短路径的节点有通路 
                v = i;
                min = D[i];
            }
        }
        if(v==-1){//如果找不到最近的点,就没有必要求最短路径了,直接输出找不到路 
            find = false;
            break;
        }
        final[v] = true;
        for(i=1;i<=G.vexnum;i++){//修改每个点到起点的最近距离 ,若修改了,则说明通过v点修改点离起点更近了,此时记录Path[i] = v; 
            if(final[i]==false && (min + G.arcs[v][i].length <D[i])){
                D[i] = min + G.arcs[v][i].length;
                Path[i] = v;//这样就把下一个最近的点连接到路径上了 
            }
        } 
        if(v == en){//到达尾节点,结束循环 
            find = true;
            break;
        }
    }
    OutPutPath(G,find,sn,en);//输出最短路径 
}
int main(){
    while(1){
        MGraph G;
        char start[30],end[30],name[30],num;//起点集、终点集、名称集、景点对应的下标 
        int sn,en,choice;//起始点、终止点 
        printf("\t\t■校园景点游览■\n"); 
        Creat_Graph(G);//创建图 
        while(1){
            printf("■用户操作:\n");
            printf("(1)景点信息  (2)最短距离\n");
            scanf("%d",&choice);
            if(choice == 1){
                printf("■请输入要查找的景点的名称: ");
                scanf("%s",name);
                num = GetSce(name, G);
                printf("名称:%s    代号:%d    简介:%s\n\n",name,G.vexs[num].sce_num,G.vexs[num].sce_intro);    
            }else if(choice == 2){
                printf("起点 & 终点:");
                scanf("%s",start);
                scanf("%s",end);
                sn = GetSce(start,G);
                en = GetSce(end,G);
                if(sn==en)
                     printf("您输入的起始位置和终止位置相等,所以不必查询.\n\n");
                else 
                     Dijkstra(G,sn,en);//输出最短路径 
            }
            printf("■请输入您的选择:\n"); 
            printf("■(0)继续查询  (1)退出 \n\n");
            int q;
            scanf("%d",&q);
            if(q){
                printf("May the code be with u!");
                exit(0);
            }
         }
     }
    return 0;
}
posted @ 2018-11-29 15:45  cruelty_angel  阅读(380)  评论(0编辑  收藏  举报