【数据结构实训】校园导游系统

[基本要求]

1、设计你的学校的校园平面图,所含景点10-15个。以图中顶点表示校园内各景点,存放景点名称、代号、简介等信息;以边表示路径,存放路径长度等相关信息。//存
√ 2、为来访客人提供图中任意景点相关信息的查询。//输出 √
3、为来访客人提供图中任意景点的问路查询,即查询任意两个景点之间的一条最短的简单路径。//最短路 √dijkstra
4、提供图中任意景点问路查询,即求任意两个景点之间的所有路径。//所有路径 //√dfs
5、提供校园图中多个景点的最佳访问路线查询,即求途经这多个景点的最佳路径。//多点最短路 √Floyd
6、区分汽车线路与步行线路。//两个结构体 √ 7、设计一实用的查询界面和功能菜单。//多个函数 √

[测试数据]

10
1 校门口 出入校园都需要经过校门口
2 教学楼 学生学习的地方,书声琅琅,学习氛围浓重
3 女生宿舍 女生休息的地方
4 男生宿舍 男生休息的地方
5 食堂 学生和老师吃饭的地方
6 鹅卵石路 校园的偏僻小径
7 亭子 冷清,一般没有人来往
8 湖边 湖面很大,不要靠近湖边玩水或扔垃圾
9 停车场 校园里车辆停放的地方
10 操场 供师生们运动的地方
12
1 2 5
1 10 7
1 6 4
2 9 6
2 8 5
3 10 3
3 5 2
4 5 3
4 8 8
5 10 3
5 8 7
6 7 4
6
1 2 5
2 3 10
2 4 9
2 9 6
3 4 4
4 9 10
24
1 6 东
1 10 东南
1 2 西南
2 1 东北
2 8 南
2 9 西南
3 10 西北
3 5 西
4 5 北
4 8 西北
5 10 北
5 3 东
5 4 南
5 8 西
6 1 西
6 7 东
7 6 西
8 2 北
8 5 东
8 4 东南
9 2 东北
10 1 西北
10 3 东南
10 5 南
12
1 2 西南
2 1 东北
2 3 东偏南
2 4 南偏东
2 9 西南
3 2 西北
3 4 西南
4 9 西偏北
4 2 北偏西
4 3 东北
9 2 东北
9 4 东南
在这里插入图片描述

[选做内容]

1、扩充道路信息,如道路类别(车道、人行道等)、沿途景色等,以至可按客人所需分别查询人行路径和车行路径或观察路径。
2、扩充每个景点的邻接景点的方向等信息,使得路径查询结果能提供详尽的导向信息。
3、实现校园导游图的仿真界面。

[代码实现]

//0!='0'
#include<queue>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<stack>
using namespace std;
#define scnaf scanf
#define ll long long
const int N=1e2+50;
const int INF=0x3f3f3f3f;
int head[2][N],cnt[2],n=10,m[2],f[2];//链式前向星: 第一个以i为顶点的边 边的个数 路径数 景点的个数 方位数 | 0人1车
int dfsv[N]={0},p[N],top=0,way;//dijkstra: 标记是否入"栈"过   存路径|"类栈"  栈中元素数
int floydp[N],floydw[N][N],pathw[N],pcnt;
//floyd: 多源最短路所需途径景点代号  floydw[i][j]从景点i到j需要途径的代号  记录多源最短路径  记录查找到的路径上景点数
void printff();
struct S
{
    char name[20],intr[50],fang[2][15][10];//名字  简介  方向
}sce[N];//景点信息
struct ss
{
    int next,to,w;//下一个以i为顶点的边的位置  该边的尾  该边的权值
}e[2][N];
void add(int x,int y,int w,int flag)//添加无向边
{
    e[flag][++cnt[flag]].to=y;
    e[flag][cnt[flag]].w=w;
    e[flag][cnt[flag]].next=head[flag][x];
    head[flag][x]=cnt[flag];
}
void scene(int k)//查询k景点信息
{
    printf("  查询景点代号为%d\n  名称:%s\n  简介:%s\n",k,sce[k].name,sce[k].intr);
}
void dij(int x,int y,int flag)//单源点最短路->dijkstra
{
    int d[N],v[N],path[N],i,j,k,t[N];
    //v[i]景点i被访问过,d[i]景点x到景点i的最短距离,path[i]=j表明从x到i最后一段是i->j
    memset(d,INF,sizeof(d));
    memset(path,INF,sizeof(path));
    memset(v,0,sizeof(v));
    d[x]=0;
    while(1)
    {
        k=-1,j=INF;
        for(i=1;i<=n;i++)
            if(d[i]<j&&!v[i])//被访问到但没有被选择过
            {
                k=i;
                j=d[i];
            }
        if(k==-1)//没有连通点或者全部选择结束
            break;
        v[k]=1;//要在进循环前标记,否则会反复访问k点
        for(i=head[flag][k];i;i=e[flag][i].next)
        {
            if(!v[e[flag][i].to]&&((d[k]+e[flag][i].w)<d[e[flag][i].to]))
                {
                    d[e[flag][i].to]=d[k]+e[flag][i].w;
                    path[e[flag][i].to]=k;
                }
        }
    }
    k=0,j=y;
    while(path[j]!=INF)
    {
        t[++k]=path[j];
        j=path[j];
    }
    if(!k)
    {
        printf("\n  您查询的两点之间不通,请重新输入\n");
        return ;
    }
    printf("\n  两景点最短路线为: ");
    for(i=k,t[0]=y;i>0;i--)
    {
        printf(" %d",t[i]);
        printf(" %s ->",sce[t[i]].fang[flag][t[i-1]]);
    }
    printf(" %d",y);
    printf("\n  两景点距离为:  %d(单位/百米)\n",d[y]);
}
void priath(int p[],int top,int way,int flag)//打印路径
{
    printf("  路径%d:",++way);
    int i;
    for(i=1;i<top;i++)
    {
        printf(" %d ",p[i]);
        printf("%s ->",sce[p[i]].fang[flag][p[i+1]]);
    }
    printf(" %d\n",p[top]);
}
void dfsway(int x,int y,int flag,int top)//深搜所有路径
{
    dfsv[x]=1;
    p[++top]=x;
    if(p[top]==y)
        priath(p,top,way,flag);
    for(int i=head[flag][x];i;i=e[flag][i].next)
        if(!dfsv[e[flag][i].to])
            dfsway(e[flag][i].to,y,flag,top);
    dfsv[x]=0;//递归. 当退到栈内点时,已经循环过,所以所有点可以共用一个标记数组
    top--;
}
void evway(int x,int y,int flag)//初始化"栈"
{
    way=top=0;
    memset(dfsv,0,sizeof(dfsv));
    dfsway(x,y,flag,top);
    if(!way)
        printf("\n  您查询的两点之间不通,请重新输入\n");
}
void pathway(int l,int r)//递归回推路径
{
    if(l==r)
        return ;
    if(floydw[l][r]==-1)
        pathw[++pcnt]=r;
    else
    {
        pathway(l,floydw[l][r]);
        pathway(floydw[l][r],r);
    }
}
void floyd(int flag)//处理多源最短距离
{
    int i,j,k,p,dp[N][N];// dp[i][j]从景点i到景点j的距离
    memset(dp,INF,sizeof(dp));
    memset(floydw,-1,sizeof(floydw));
    for(i=1;i<=n;i++)
        dp[i][i]=0;
    for(i=1;i<=n;i++)
    {
        for(j=head[flag][i];j;j=e[flag][j].next)
            dp[i][e[flag][j].to]=e[flag][j].w;
    }
    for(k=1;k<=n;k++)//景点
        for(i=1;i<=n;i++)//遍历数组松弛每对景点
            for(j=1;j<=n;j++)
                if((dp[i][k]+dp[k][j])<dp[i][j])
                {
                    dp[i][j]=dp[i][k]+dp[k][j];
                    floydw[i][j]=k;
                }
    for(i=2,k=1,pcnt=0;floydp[i];i++)//i是终点 k是起点 pcnt是
    {
        for(j=1,p=0;j<=pcnt;j++)
            if(floydp[i]==pathw[j])
                p=1;
        if(dp[floydp[k]][floydp[i]]==INF)
        {
            printf("  您查询的地点不互通,请重新输入\n");
            return ;
        }
        if(!p)
        {
            pathway(floydp[k],floydp[i]);
            k=i;
        }
    }
    pathw[0]=floydp[1];//出发点
    for(i=0;i<pcnt;i++)
    {
        printf("%d",pathw[i]);
        printf(" %s -> ",sce[pathw[i]].fang[flag][pathw[i+1]]);
    }
    printf("%d",pathw[i]);
}
int main()
{
    int i,j,k,x,y,w,p,flag=0;
    printf("请输入景点个数\n");
    scnaf("%d",&n);
    printf("\n请输入景点信息(代号 名称 简介):\n");
    for(i=1;i<=n;i++)
        scnaf("%d%s%s",&j,&sce[j].name,&sce[j].intr);
    printf("\n请输入景点步行路线数:\n");
    scanf("%d",&m[0]);
    printf("\n请依次输入景点步行路线:\n");
    for(i=1;i<=m[0];i++)
    {
        scnaf("%d%d%d",&x,&y,&w);
        add(x,y,w,0);
        add(y,x,w,0);
    }
    printf("\n请输入景点汽车路线数:\n");
    scanf("%d",&m[1]);
    printf("\n请依次输入景点汽车路线:\n");
    for(i=1;i<=m[1];i++)
    {
        scnaf("%d%d%d",&x,&y,&w);
        add(x,y,w,1);
        add(y,x,w,1);
    }
    printf("\n请输入步行方位数:\n");
    scanf("%d",&f[0]);
    printf("\n请依次输入景点间步行的方位:\n");
    for(i=1;i<=f[0];i++)
    {
        scnaf("%d%d",&x,&y);
        scanf("%s",&sce[x].fang[0][y]);
    }
    printf("\n请输入汽车方位数:\n");
    scanf("%d",&f[1]);
    printf("\n请依次输入景点间步行的方位:\n");
    for(i=1;i<=f[1];i++)
    {
        scnaf("%d%d",&x,&y);
        scnaf("%s",&sce[x].fang[1][y]);
    }
    while(1)
    {
        printf("请输入:\n 0.退出\n 1.查询任意景点信息\n 2.查询任意两个景点最短路线\n");
        printf(" 3.查询任意两个景点所有路线\n 4.查询多个景点最佳路线\n 5.导游仿真图\n");
        scanf("%d",&p);
        if(!p)
            break;
        switch(p)
        {
            case 1:
            {
                printf("\n请输入查询景点的代号:\n");
                scanf("%d",&k);
                scene(k);
                break;
            }
            case 2:
            {
                printf("\n请输入查询路线类型:\n 0.步行\n 1.汽车\n");
                scanf("%d",&flag);
                printf("\n请输入两景点的代号(将默认第一个数字为起点):\n");
                scnaf("%d%d",&x,&y);
                dij(x,y,flag);
                break;
            }
            case 3:
            {
                printf("\n请输入查询路线类型:\n 0.步行\n 1.汽车\n");
                scnaf("%d",&flag);
                printf("\n请输入两景点代号(将默认第一个数字为起点):\n");
                scnaf("%d%d",&x,&y);
                evway(x,y,flag);
                break;
            }
            case 4:
            {
                printf("\n请输入查询路线类型:\n 0.步行\n 1.汽车\n");
                scnaf("%d",&flag);
                printf("\n请依次输入景点代号(将默认第一个数字为起点),输入数字0结束\n");
                for(i=1;;i++)
                {
                    scanf("%d",&floydp[i]);
                    if(!floydp[i])
                        break;
                }
                floyd(flag);
                break;
            }
            case 5:printff();break;
        }
    }
    return 0;
}
void printff()
{
    printf("\n步行导游仿真图:\n");
    printf("           1校门口***6鹅卵石路***7亭子\n");
    printf("              * *              \n");
    printf("            *     *            \n");
    printf("          *         *          \n");
    printf("      2教学楼        10操场    \n");
    printf("      *  *            *        \n");
    printf("    *    *            *        \n");
    printf("  *      *            *        \n");
    printf("9停车场 8湖边*******5食堂***3女生宿舍\n");
    printf("          *           *        \n");
    printf("            *****     *        \n");
    printf("                  **4男生宿舍  \n");
    printf("\n\n汽车导游仿真图:\n");
    printf("           1校门口\n");
    printf("              *               \n");
    printf("            *                 \n");
    printf("          *                   \n");
    printf("      2教学楼                 \n");
    printf("      *   *****               \n");
    printf("    *         *****           \n");
    printf("  *                *****      \n");
    printf("9停车场                 *****3女生宿舍\n");
    printf("   ****                    ** \n");
    printf("       ****             **    \n");
    printf("           ****4男生宿舍      \n");
}
  • 2
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值