制定游玩方案

任务要求:

1. 设计数据结构,存储该导游图,只需存储各个景点的名称以及之间的距离即可(距离数据可以自己定,景点数量至少15个)

2. 输入一个起点景点,一个要前往的景点,输出最短路径。

3. 输入一个起点景点,设计一条合理旅游路线,游玩所有景点。(提示:可按照深度优先搜索算法,选择下一个景点的原则可以是离当前景点最近的没有去过的景点)

4. 输入一个起点景点,设计一条合理旅游路线,游玩用户指定的多个景点。

1.分析设计

(此处写程序的设计思路,流程图、接口设计、类定义等)

3.1.设计思路

  • 设计数据结构:使用图的邻接矩阵表示法来存储景点之间的关系,定义顶点和边的结构。
  • 实现算法:分别实现Dijkstra算法、DFS算法和Prime算法,用于寻找最优旅游路线。
  • 用户交互:设计用户界面,接收用户输入,并调用相应的函数进行处理。
  • 输出结果:根据用户需求,将最优旅游路线打印输出。
  • 图的邻接矩阵表示法:使用二维数组来表示景点之间的关系,数组元素值表示两个景点之间的距离。
  • 顶点结构定义:包含景点名称和编号等信息。
  • 边的结构定义:包含起点、终点以及边的权重(距离)等信息。

3.2.流程图

三大算法流程图:

3.3.接口设计

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

3.4.类定义

  • 主函数:规定系统的主要流程,接收用户输入并调用相应函数进行处理。
  • Dijkstra算法函数:计算起点到其他景点的最短路径,并返回最优路径和距离。
  • DFS算法函数:遍历图中的所有路径,并找出满足条件的最优路径。
  • Prime算法函数:生成最小生成树,并返回最优路径和权重。

G->edges[a][b]的方式存储路径,以G->V[n].name的方式存储每一个游玩项目的名称,定义如下:

typedef struct VertexType{

char name[50]; 

}VertexType;

typedef struct graph{

VertexType V[16];

int edges[MAXVN][MAXVN];

int n,e;

}MGraph;

2.程序实现

(此处描述程序数据结构核心算法的实现,遇到的主要问题及解决办法等。注意:不需要粘贴全部代码,只贴核心重要的部分;需要有必要的注释,不能只贴代码)

任务一图的存储方式为邻接矩阵,以G->edges[a][b]的方式存储路径,以G->V[n].name的方式存储每一个游玩项目的名称,定义如下:

typedef struct VertexType{

char name[50]; 

}VertexType;

typedef struct graph{

VertexType V[16];

int edges[MAXVN][MAXVN];

int n,e;

}MGraph;

任务二输入一个起点景点,一个要前往的景点,输出最短路径采用的是迪杰斯特拉算法求最短路径,将从起点开始出发每一个结点的上一步存储到path[]数组中,将起点到其余结点的路程存储到dis[]数组中,比较直达与经过一个结点后到达的路径长短,然后进行path[]与dis[]的改变。

void Dijkstra(MGraph *G,int start,int end)

{

    int dis[MAXV];

    int path[MAXV];

    int s[MAXV];

    int mindis;

    int i,j,k;

    for(i=1;i<=G->n;i++){

        dis[i]=G->edges[start][i];

        s[i]=0;

      if(G->edges[start][i]<INF)

      path[i]=start;

      else

      path[i]=-1;

    }

    s[start]=1;

    for(i=1;i<=G->n;i++){

        mindis=INF;

       k=start;

        for(j=1;j<=G->n;j++){

            if(mindis>dis[j] &&s[j]==0){

                mindis=dis[j];

                k=j;

            }

        }

       s[k]=1;

        for(j=1;j<=G->n;j++){

           

            if(dis[j]>dis[k]+G->edges[k][j]&&s[j]==0&&G->edges[k][j]<INF){

                dis[j]=dis[k]+G->edges[k][j];

                path[j]=k;

            }

        }

    }

    dispath(dis,path,s,G,start,end);   

}

具体代码实现见课本,注:课本上的输出为%d<-%d<-…形式的,为了使其逆转,假设函数的定义为Dijkstra(MGraph *G,int start,int end)那么只需将输入编写如下,即可实现正序打印

printf("请输入起点景点和要前往的景点序号:");

scanf("%d %d",&end,&start);

Dijkstra(G,start,end);

任务三输入一个起点景点,设计一条合理旅游路线,游玩所有景点。

采用的是邻接矩阵的深度搜索遍历(这个实现方法简单而且大部分情况都是选择最近的景点作为下一步),不过值得注意的是要想完成多次的路线查询,需要在case2后面加一个for循环,将visited[]重新置为false,否则结果会出错

bool visited[MaxVertexNum];

 void DFS(MGraph *G,int k){

    printf("%s ",G->V[k].name);

    visited[k]=true;

    int i;

     for(i=1;i<=G->n;i++){

      if(G->edges[k][i]!=0&&G->edges[k][i]!=INF&&!visited[i])

        DFS(G,i);

     }

 }

任务四输入一个起点景点,设计一条合理旅游路线,游玩用户指定的多个景点。这个任务采用的是prime算法最小生成树经过结点的打印,将起始节点和想要经过的结点复制到一个新的MGraph结构体中去,然后依次复制结点之间的路径,各个节点的名称,各个结点之间的路径需要用迪杰斯特拉算法依次生成使用的是

int djs(MGraph *G,int start,int end)(只是将迪杰斯特拉的输出改为dis[i]).

函数,最后打印出的是两结点的最短路径,然后再运用prime算法对新结构体中的数据进行处理

源代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXVN 100
#define MAXV 10010
#define max 1000
#define INF 32767
typedef enum {false, true} bool;
#define MaxVertexNum 20  /* 最大顶点数设为20*/
typedef struct VertexType{
char name[50];	
}VertexType;
typedef struct graph{
VertexType V[20];
int edges[MAXVN][MAXVN]; 
int n,e; 
}MGraph;
void menu() //菜单函数
{
printf(" ++++++++++++++++++++请选择++++++++++++++++++++\n");
printf("                1.最短路径查询\n");
printf("                2.旅游路线推荐\n");
printf("                3.私人定制旅游路线\n");
printf("                4.退出\n");
printf("+++++++++++++欢迎来到迪士尼乐园++++++++++++++\n");
printf("\n");
}
void creat(MGraph *G){
int i,j,k,n,e;
G->n=16;
G->e=20;
n=G->n;
e=G->e;
for(i=1;i<=n;i++){
    for(j=i;j<=n;j++){
        G->edges[i][j]=G->edges[j][i]=INF;
}
}
strcpy(G->V[1].name, "1.星球大战");
strcpy(G->V[2].name, "2.极速光轮");
strcpy(G->V[3].name, "3.星际营救");
strcpy(G->V[4].name, "4.太空幸会史迪奇");
strcpy(G->V[5].name, "5.喷气背包飞行");
strcpy(G->V[6].name, "6.小飞侠天空奇遇");
strcpy(G->V[7].name, "7.小飞条");
strcpy(G->V[8].name, "8.梦幻沙龙");
strcpy(G->V[9].name, "9.童话时光");
strcpy(G->V[10].name, "10.宴会厅");
strcpy(G->V[11].name, "11.晶彩奇航");
strcpy(G->V[12].name, "12.夜光幻影");
strcpy(G->V[13].name, "13.爱丽丝梦游仙境");
strcpy(G->V[14].name, "14.漫月轩");
strcpy(G->V[15].name, "15.七个小矮人过山车");
strcpy(G->V[16].name, "16.旋转木马");
    G->edges[1][3]=10;
    G->edges[1][2]=20;
    G->edges[4][5]=10;
    G->edges[3][4]=30;
    G->edges[5][6]=30;
    G->edges[5][7]=20;
    G->edges[6][8]=10;
    G->edges[8][9]=10;
    G->edges[9][10]=10;
    G->edges[8][10]=10;
    G->edges[7][11]=20;
    G->edges[10][12]=10;
    G->edges[11][12]=10;
    G->edges[10][13]=20;
    G->edges[9][14]=30;
    G->edges[12][15]=40;
    G->edges[13][15]=20;
    G->edges[14][15]=30;
     G->edges[14][16]=30;
      G->edges[9][16]=20;
    	for(i=1;i<=n;i++){
    	 for(j=i+1;j<=n;j++){
    	 G->edges[j][i]=G->edges[i][j];
	}
	}
}
//深度优先设计旅游路线
 bool visited[MaxVertexNum];
 void DFS(MGraph *G,int k){
 	printf("%s ",G->V[k].name);
 	visited[k]=true;
 	int i;
	 for(i=1;i<=G->n;i++){
	 	if(G->edges[k][i]!=0&&G->edges[k][i]!=INF&&!visited[i])
	 	DFS(G,i);
	 }
 }
 //dijiesitra算法最短路径
void Dijkstra(MGraph *G,int start,int end)
{
    int dis[MAXV];
    int path[MAXV];
    int s[MAXV];
    int mindis;
    int i,j,k;
    for(i=1;i<=G->n;i++){
        dis[i]=G->edges[start][i];
        s[i]=0;
      if(G->edges[start][i]<INF)
      path[i]=start;
      else
      path[i]=-1;
    }
    s[start]=1;
    for(i=1;i<=G->n;i++){
        mindis=INF;
		k=start;
        for(j=1;j<=G->n;j++){
            if(mindis>dis[j] &&s[j]==0){
                mindis=dis[j];
                k=j;
            }
        }
       s[k]=1;
        for(j=1;j<=G->n;j++){
        	
            if(dis[j]>dis[k]+G->edges[k][j]&&s[j]==0&&G->edges[k][j]<INF){
                dis[j]=dis[k]+G->edges[k][j];
                path[j]=k;
            }
        }
    }
    dispath(dis,path,s,G,start,end);    
}
void dispath(int dis[],int path[],int s[],MGraph *G,int v,int e){
	int i,k;
		if(s[e]==1){
		k=e;
			printf("景点%d到景点%d的最短路径为:",e,v);
		
			while(k!=v){
				printf(" %s --> ",G->V[k].name);
				k=path[k];
			}
			printf(" %s",G->V[v].name);
			printf("\n总路程为%d",dis[e]);
		}
		else
		printf("不存在路径"); 
}
int djs(MGraph *G,int start,int end)
{
    int dis[MAXV];
    int path[MAXV];
    int s[MAXV];
    int mindis;
    int i,j,k;
    for(i=1;i<=G->n;i++){
        dis[i]=G->edges[start][i];
        s[i]=0;
      if(G->edges[start][i]<INF)
      path[i]=start;
      else
      path[i]=-1;
    }
    s[start]=1;
    for(i=1;i<=G->n;i++){
        mindis=INF;
		k=start;
        for(j=1;j<=G->n;j++){
            if(mindis>dis[j] &&s[j]==0){
                mindis=dis[j];
                k=j;
            }
        }
       s[k]=1;
        for(j=1;j<=G->n;j++){
        	
            if(dis[j]>dis[k]+G->edges[k][j]&&s[j]==0&&G->edges[k][j]<INF){
                dis[j]=dis[k]+G->edges[k][j];
                path[j]=k;
            }
        }
    }  
    return dis[end];
}
void personal(MGraph *G,int start,int num){
	int i,j,a,b;
	MGraph *Q;
	Q=(MGraph *)malloc(sizeof(MGraph));
	for(i=1;i<=num+1;i++){
    for(j=1;j<=num+1;j++){
        Q->edges[i][j]=INF;
}}
	Q->n=num+1;
	Q->e=num*(num+1)/2;
	    int node[MAXVN];
	    node[1]=start;
	    printf("请输入经过的景点编号(不包含起始点):");
	for(i=2;i<=Q->n;i++){
		scanf("%d",&node[i]);
	}
	for(i=1;i<=Q->n;i++){
		for(j=i;j<=Q->n;j++){
			a=node[i];
			b=node[j];
			Q->edges[i][j]=Q->edges[j][i]=djs(G,a,b);
		
		}
			strcpy(Q->V[i].name,G->V[node[i]].name);
	}
prime(Q,start,node);
}
void prime(MGraph* G,int v,int node[]) {
    int visit[MAXVN]={0};           //点是否访问过,未访问0,访问1
    visit[1] = 1;               //起始点已经访问过 
    int short_length[MAXVN];        //访问过的点的集合到未访问过点的集合的最小路径
 int m,i,j;
    for (i = 1; i <= G->n; i++) 
        short_length[i] = G->edges[1][i];        //初始化,此时只有起始点
    short_length[1] = 0;        //起始点路径为0
    printf("%s",G->V[1].name);
    for (i = 1; i <G->n; i++)       
    {
        int min_length = max;
        int k=0;
        for (j = 1; j <=G->n; j++) {   //在所有未访问过的边里找到最短路径
            if (min_length > short_length[j] && visit[j] == 0) {
                k = j;
                min_length = short_length[j];
            }
        }
        visit[k] = 1;
        printf("-->%s",G->V[k].name);
        for (j = 1; j <= G->n; j++) {
            if (visit[j] == 0 && short_length[j] > G->edges[k][j])
                short_length[j] = G->edges[k][j];
        }
 
    }
    return;
}

int main(){
     MGraph *G;
    int i,k;
    int num;
	int start,end;
	int n,flag;
	char a; 
     G=(MGraph *)malloc(sizeof(MGraph));
    
          printf("\t\t\t迪士尼乐园游玩攻略\n");
	float x,y,z;
	for(y=1.5;y>-1.5;y-=0.1){
	for(x=-1.5;x<1.5;x+=0.05){
	z=x*x+y*y-1;
	putchar(z*z*z-x*x*y*y*y <=0.0 ? '@' : ' ');
	}
	system("color 0c");
	putchar('\n');
	}
	printf("            "); 
    printf("++++++++++++++++++++++++++++++++++++++\n");
    printf("\t    +                                     +\n");
    printf("\t    +         欢迎来到迪士尼乐园          +\n");
    printf("\t    +                                     +\n");
    printf("\t    +                                     +\n");
    printf("\t    +         请按任意键跳转到菜单        +\n");
    printf("\t    +                                     +\n");
    printf("\t    +          计科2202_郝雨川            +\n");
    printf("\t    ++++++++++++++++++++++++++++++++++++++\n");

    getchar(); //等待用户输入任意键 
    system("cls");
    system("color 07");
	creat(G);
	menu(); 
while(flag==0)
	{
    printf("请选择你需要操作的步骤(1--4):\n");
scanf("%d",&n);
if(n>=1&&n<=4)
{
flag=1;
}
else
{
flag=0;
printf("您输入有误,请重新选择!");
}
}
while(flag==1)
{
switch(n)
{
case 1:printf("最短路径查询\n");
printf("游玩项目序号(具体地图见大作业报告)\n1.星球大战\n2.极速光轮\n3.星际营救\n4.太空幸会史迪奇\n5.喷气背包飞行\n6.小飞侠天空奇遇\n7.小飞条\n8.梦幻沙龙\n9.童话时光\n10.宴会厅\n11.晶彩奇航\n12.夜光幻影\n13.爱丽丝梦游仙境\n14.漫月轩\n15七个小矮人过山车\n");
printf("请输入起点景点和要前往的景点序号:");
scanf("%d %d",&end,&start);
Dijkstra(G,start,end);
printf("\n");
break;
case 2:printf(" 游玩路线推荐\n");
int i;
for(i=1;i<=G->n;i++){
	visited[i]=false;
}
printf("\n");
	printf("游玩项目序号(具体地图见大作业报告)\n1.星球大战\n2.极速光轮\n3.星际营救\n4.太空幸会史迪奇\n5.喷气背包飞行\n6.小飞侠天空奇遇\n7.小飞条\n8.梦幻沙龙\n9.童话时光\n10.宴会厅\n11.晶彩奇航\n12.夜光幻影\n13.爱丽丝梦游仙境\n14.漫月轩\n15七个小矮人过山车\n");
printf("请输入你想最先游玩的项目序号:") ;
     scanf("%d",&k);
     printf("为您推荐的游玩路线为: ");
     DFS(G,k);
break;
case 3:printf("私人定制路线\n");
printf("\n");
	printf("游玩项目序号(具体地图见大作业报告)\n1.星球大战\n2.极速光轮\n3.星际营救\n4.太空幸会史迪奇\n5.喷气背包飞行\n6.小飞侠天空奇遇\n7.小飞条\n8.梦幻沙龙\n9.童话时光\n10.宴会厅\n11.晶彩奇航\n12.夜光幻影\n13.爱丽丝梦游仙境\n14.漫月轩\n15七个小矮人过山车\n");
printf("\n请输入起始景点编号:");
    scanf("%d", &start);
    printf("请输入要经过的景点数量(不包含起始点):");
    scanf("%d", &num);
personal(G,start,num);
break;
case 4:exit(0);
break;
default:break;
}
getchar();
printf("\n");
printf("是否继续进行(y or n):\n");
scanf("%c",&a);
if(a=='y')
{
flag=1;
system("cls");
menu(); //调用菜单函数
printf("请再次选择你需要操作的步骤(1--4):\n");
scanf("%d",&n);
printf("\n");
}
else
exit(0);
}
}

运行结果展示:

开始界面:

 

最短路径查询:

旅游路线推荐:

私人定制旅游路线:

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值