27.交通咨询系统——最低花费(***)
描述
设计一个交通咨询系统,能让旅客咨询从任一个城市到另一个城市之间的最低花费。
(1)顶点表示城市,边表示城市之间的交通关系,边的权值表示两个城市之间交通所需要的时间。
(2)图采用邻接矩阵存储结构实现。
(3)输出两个城市之间的最低花费。
(4)在主函数中调用菜单函数调试程序。
初始代码:
#include <stdio.h>
#include<malloc.h>
#include <stdlib.h>
#define MaxVerNum 30//定义存储的最大个数
#define NIF 32767 //定义无穷大
#define false 0
#define true 1
typedef char VertexType; //定义顶点表类型是字符型
typedef int Edgetype;
/**建立结构体**/
typedef struct {
VertexType vexs[MaxVerNum];/*顶点表*/
Edgetype edges[MaxVerNum][MaxVerNum]; //边表
int n, e; //顶点数和边数
} MGraph;
int menu_select()
{
int sn;
printf("-----------交通咨询系统——最低花费----------------------
");
printf("1构建图
");
printf("2输出两个城市之间的最低花费
");
printf("3退出
");
printf(" 请选择1--3: ");
for(;;) //菜单功能选择
{
scanf("%d",&sn);
getchar();
if(sn<1 || sn>3)
printf("
输入选择错误,请重新选择 1--3: ");
else
break;
}
return sn;
}
/*TODO: 创建邻接矩阵
功能描述: 功能描述:创建邻接矩阵,初始设置节点自己到自己为0,其他为NIF,创建边时,根据输入设置权值。
参数说明:MG-MGraph型指针参数
返回值说明:无
*/
void CreatGraph(MGraph *G) { /**接口参数:图的结构体指针**/
int i, j,weight, k;
printf("请输入城市数和路线数(比如:4,5): ");
scanf("%d,%d", &(G->n), &(G->e)); //顶点数及边数
printf("
请输入城市数据: ");
for (i = 0; i < G->n; i++) {
scanf("%s", &(G->vexs[i]));/**输入顶点信息**/
}
for (k = 0; k < G->e; k++) {
printf("
请输入存在路线的两个城市以及票价(比如:2,3,4): ");
scanf("%d,%d,%d", &i, &j ,&weight);/**输入边的信息**/
}
}
/*TODO: Floyd求得两个顶点间最短路径
功能描述:用Floyd算法求出from到to两点最小路径并返回(from,to是用创建图时,存入的数组的下标表示)
参数说明:G-MGraph型指针参数
from-int型 最短路径开始顶点
to-int型 最短路径结束顶点
返回值说明:int型最短路径
*/
int Floyd(MGraph *G, int from, int to) {
}
/**************主函数部分***************/
void main()
{
int from, to, result;
MGraph *S;
S = (MGraph*) malloc(sizeof(MGraph));
for(;;) // 无限循环,选择0 退出
{
switch(menu_select())
{
case 1:
CreatGraph(S);
break;
case 2:
printf("请输入两个城市根据从0开始(比如0,1)
");
scanf("%d,%d", &from, &to);
result = Floyd(S, from, to);
printf("最低花费是 %d
", result);
break;
case 3:
printf(" 再见!
");
return;
} // switch语句结束
} // for循环结束
} // main()函数结束
思路:
本题采用Floyd算法,思路较为简单,以邻接矩阵存储的无向网为初始状态,此时矩阵中的每个值都代表两个顶点间的路径长度,Floyd算法的思路是在每两个顶点(源点和重点)间增加新的顶点(借助其他顶点)进行试探,试探增加顶点后的路径长度是否会变短,增加顶点后若变短,则用增加顶点后的路径长度取代原路径长度。对于原表中的每个顶点都要进行试探,确定增加了它们后路径是否会变短,因此有状态转移方程
G->edges[i][j] = G->edges[i][k] + G->edges[k][j]
其中k取遍所有顶点。
更具体的解释如下:
(更为详细的解释,移步至——https://www.cnblogs.com/wangyuliang/p/9216365.html)
实现:
#include <stdio.h>
#include<malloc.h>
#include <stdlib.h>
#define MaxVerNum 30//定义存储的最大个数
#define NIF 32767 //定义无穷大
#define false 0
#define true 1
typedef char VertexType; //定义顶点表类型是字符型
typedef int Edgetype;
/**建立结构体**/
typedef struct
{
VertexType vexs[MaxVerNum];/*顶点表*/
Edgetype edges[MaxVerNum][MaxVerNum]; //边表
int n, e; //顶点数和边数
} MGraph;
int menu_select()
{
int sn;
printf("-----------交通咨询系统——最低花费----------------------
");
printf("1构建图
");
printf("2输出两个城市之间的最低花费
");
printf("3退出
");
printf(" 请选择1--3: ");
for(;;) //菜单功能选择
{
scanf("%d",&sn);
getchar();
if(sn<1 || sn>3)
printf("
输入选择错误,请重新选择 1--3: ");
else
break;
}
return sn;
}
/*TODO: 创建邻接矩阵
功能描述: 功能描述:创建邻接矩阵,初始设置节点自己到自己为0,其他为NIF,创建边时,根据输入设置权值。
参数说明:MG-MGraph型指针参数
返回值说明:无
*/
void CreatGraph(MGraph *G) /**接口参数:图的结构体指针**/
{
int i, j,weight, k;
printf("请输入城市数和路线数(比如:4,5): ");
scanf("%d,%d", &(G->n), &(G->e)); //顶点数及边数
printf("
请输入城市数据: ");
for (i = 0; i < G->n; i++)
{
scanf("%s", &(G->vexs[i]));/**输入顶点信息**/
}
for(i=0;i<G->n;i++)
{
for(j=0;j<G->n;j++)
{
if(i == j)
{
G->edges[i][j] = 0;
}
else
{
G->edges[i][j] = NIF;
}
}
}
for (k = 0; k < G->e; k++)
{
printf("
请输入存在路线的两个城市以及票价(比如:2,3,4): ");
scanf("%d,%d,%d", &i, &j,&weight); /**输入边的信息**/
G->edges[i][j] = weight;
G->edges[j][i] = weight;
}
}
/*TODO: Floyd求得两个顶点间最短路径
功能描述:用Floyd算法求出from到to两点最小路径并返回(from,to是用创建图时,存入的数组的下标表示)
参数说明:G-MGraph型指针参数
from-int型 最短路径开始顶点
to-int型 最短路径结束顶点
返回值说明:int型最短路径
*/
int Floyd(MGraph *G, int from, int to)
{
int i,j,k;
for(k=0;k<G->n;k++)
{
for(i=0;i<G->n;i++)
{
for(j=0;j<G->n;j++)
{
if(G->edges[i][j] > G->edges[i][k] + G->edges[k][j])
{
G->edges[i][j] = G->edges[i][k] + G->edges[k][j];//Floyd算法的状态转移方程
}
}
}
}
return G->edges[from][to];
}
/**************主函数部分***************/
int main()
{
int from, to, result;
MGraph *S;
S = (MGraph*) malloc(sizeof(MGraph));
for(;;) // 无限循环,选择0 退出
{
switch(menu_select())
{
case 1:
CreatGraph(S);
break;
case 2:
printf("请输入两个城市根据从0开始(比如0,1)
");
scanf("%d,%d", &from, &to);
result = Floyd(S, from, to);
printf("最低花费是 %d
", result);
break;
case 3:
printf(" 再见!
");
return 0;
} // switch语句结束
} // for循环结束
} // main()函数结束
测试输入:
1,12,14 A B C D H L K J I E F G 0,1,1 1,2,1 2,3,1 3,4,1 4,5,1 5,6,1 6,7,1 7,8,1 8,9,1 9,0,1 0,3,2 0,10,1 10,11,2 11,5,1 2 3,9 3
测试输出:
答案输出:-----------交通咨询系统——最低花费----------------------
1构建图
2输出两个城市之间的最低花费
3退出
请选择1--3: 请输入城市数和路线数(比如:4,5):
请输入城市数据:
请输入存在路线的两个城市以及票价(比如:2,3,4):
请输入存在路线的两个城市以及票价(比如:2,3,4):
请输入存在路线的两个城市以及票价(比如:2,3,4):
请输入存在路线的两个城市以及票价(比如:2,3,4):
请输入存在路线的两个城市以及票价(比如:2,3,4):
请输入存在路线的两个城市以及票价(比如:2,3,4):
请输入存在路线的两个城市以及票价(比如:2,3,4):
请输入存在路线的两个城市以及票价(比如:2,3,4):
请输入存在路线的两个城市以及票价(比如:2,3,4):
请输入存在路线的两个城市以及票价(比如:2,3,4):
请输入存在路线的两个城市以及票价(比如:2,3,4):
请输入存在路线的两个城市以及票价(比如:2,3,4):
请输入存在路线的两个城市以及票价(比如:2,3,4):
请输入存在路线的两个城市以及票价(比如:2,3,4): -----------交通咨询系统——最低花费----------------------
1构建图
2输出两个城市之间的最低花费
3退出
请选择1--3: 请输入两个城市根据从0开始(比如0,1)
最低花费是 3
-----------交通咨询系统——最低花费----------------------
1构建图
2输出两个城市之间的最低花费
3退出
请选择1--3: 再见!