[基本要求]
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");
}