数据结构—图及其应用(交通问题,实现最短路径、最短时间、最少费用查询)

数据结构—图及其应用(交通问题,实现最短路径、最短时间、最少费用查询)

1、任务描述

(1)、任务:

设计一个城市交通咨询模拟系统,利用该系统实现至少两种最优决策:最短路程到达、最省时到达等线路规划。

(2)、内容:

用户驾车出行由于出行目的的不同对道路路线选择的要求也有不同。例如,有的希望在途中的路程尽可能短,有的则可能希望路程中时间最短。为了能满足广大旅客的需求,编制一个城市交通咨询模拟系统,选取城市部分位置、道路抽象为程序所需要图的顶点和边,并以城市道路长度(路程),道路的某时段的速度等信息作为图结点中的弧信息,为旅客提供这两种最优决策的交通咨询。

2、测试方案

在这里插入图片描述

3、测试结果

(1)、最短路径查询
在这里插入图片描述
(2)、最短时间查询
在这里插入图片描述
(3)、 最少花费查询
在这里插入图片描述
(4)、打印地图信息
在这里插入图片描述

4、代码

/*
	写在前面:
	<1> 输入注意事项
	需要输入输入每条路的起点、终点、路的长度、速度,
	在输入完成后需要回车,然后键入{【Ctrl+Z】+【Enter】}*3 !!!
	(编译环境VS2017)

	<2>  计费规则
	小于等于 2 km 的时候一律按 5 yuan收费,
	大于等于 2 km 的部分按照 1 yuan/km 计费。
*/

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

#define INF 99999999
#define Max_Num 50						//顶点个数最大值

typedef int WeightType;
typedef int Vertex;

typedef struct ENode *ptrToENode;
struct ENode {  // 边 
	Vertex V1, V2;    // 有向边<V1,V2> 
	WeightType Length,Speed;  // 权重 
};
typedef ptrToENode Edge;

int Map_M[Max_Num][Max_Num];			//保存地图的数组
double Map_Time[Max_Num][Max_Num];	    //保存地图的速度
double Map_Money[Max_Num][Max_Num];		//保存票价
int Path_Length[Max_Num][Max_Num],		//用来存放最短路径
	Path_Time[Max_Num][Max_Num],		//用来存放最短时间
	Path_Money[Max_Num][Max_Num];		//用来存放最低费用

void Menu();
void Old_Map();
void New_Map();
void Floyd(int(*e)[Max_Num], double(*t)[Max_Num], double (*m)[Max_Num],int n);
void Floyd_Length(int(*e)[Max_Num], int n, int start, int end);
void Floyd_Time(double(*e)[Max_Num], int n, int start, int end);
void Floyd_Money(double(*e)[Max_Num], int n, int start, int end);
void PrintfMap();

int main()
{
	int Mu = 5;
	Menu();
	while (scanf("%d", &Mu), Mu != 0)
	{
		switch (Mu)
		{
		case 1: Old_Map(); break;
		case 2: New_Map(); break;
		case 3: PrintfMap(); break;
		case 4: system("cls"); break;
		default:printf("\n请输入正确指令!!!"); break;
		}

		Menu();
	}
	printf("\n成功退出!");
	return 0;
}

void Menu()
{
	printf("\n  ---选择使用已保存的地图:1---\n");
	printf("\n  ---选择重新录入地图信息:2---\n");
	printf("\n  -------打印地图信息:3-------\n");
	printf("\n  ---------清屏:4-------------\n");
	printf("\n  ---------退出:0-------------\n");
}
//使用原有地图
void Old_Map()
{
	int i, j;
	FILE *fp;
	int count = 0;
	//读入文档count.txt
	if ((fp = fopen("count.txt", "r")) == NULL)
	{
		printf("File open failed!\n");
		exit(0);
	}
	fscanf(fp, "%d", &count);
	fclose(fp);
	printf("顶点个数 == %d\n", count);
	if (count == 0)
	{
		printf("\n信息读入错误!!\n错误原因:没有已保存的地图,请选择重新输入地图信息!!\n");
		return;
	}

	//读入文档map.txt
	if ((fp = fopen("map.txt", "r")) == NULL)
	{
		printf("File open failed!\n");
		exit(0);
	}
	for (i = 1; i <= count; i++)
		for (j = 1; j <= count; j++)
		{
			fscanf(fp, "%d", &Map_M[i][j]);
		}
	fclose(fp);

	//读入文档map_speed.txt
	if ((fp = fopen("map_speed.txt", "r")) == NULL)
	{
		printf("File open failed!\n");
		exit(0);
	}
	for (i = 1; i <= count; i++)
		for (j = 1; j <= count; j++)
		{
			fscanf(fp, "%lf", &Map_Time[i][j]);
		}
	fclose(fp);

	//读入票价信息map_money.txt
	if ((fp = fopen("map_money.txt", "r")) == NULL)
	{
		printf("File open failed!\n");
		exit(0);
	}
	for (i = 1; i <= count; i++)
		for (j = 1; j <= count; j++)
		{
			fscanf(fp, "%lf", &Map_Money[i][j]);
			
		}
	fclose(fp);

	Floyd(Map_M, Map_Time, Map_Money,count);
}
//新录入地图
void New_Map()
{
	//map数组初始化
	int i, j;
	for (i = 0; i < Max_Num; i++)
		for (j = 0; j < Max_Num; j++)
			if (i == j)
			{
				Map_M[i][j] = 0;
				Map_Time[i][j] = 0;
				Map_Money[i][j] = 0;
			}

			else {
				Map_M[i][j] = INF;
				Map_Time[i][j] = INF;
				Map_Money[i][j] = INF;
			}

	printf("\n请输入每条路的起点、终点、路的长度、速度\n(中间以空格隔开,按下Ctrl+Z结束输入):\n");
	Edge E;
	E = (Edge)malloc(sizeof(struct ENode));
	int count = 0;
	//地图写入
	while (scanf("%d %d %d %d", &E->V1, &E->V2, &E->Length, &E->Speed) != EOF)		//money为每公里票价
	{
		Map_M[E->V1][E->V2] = E->Length;
		Map_M[E->V2][E->V1] = E->Length;
		Map_Time[E->V1][E->V2] = (E->Length*1.0) / E->Speed;
		Map_Time[E->V2][E->V1] = (E->Length*1.0) / E->Speed;
		if (E->Length <= 2)
		{
			Map_Money[E->V1][E->V2] = 5;
			Map_Money[E->V1][E->V2] = 5;
		}
		else
		{
			Map_Money[E->V1][E->V2] = 5 + E->Length * 1.0 * 3;
			Map_Money[E->V2][E->V1] = 5 + E->Length * 1.0 * 3;
		}
		printf("%d 地到 %d 地所需时间为:%.2f h \n", E->V1, E->V2, Map_Time[E->V1][E->V2]);
		printf("%d 地到 %d 地所需费用为:%.2f yuan \n\n", E->V1, E->V2, Map_Money[E->V1][E->V2]);
		count++;
	}
	
	//将地图存入文件map.txt
	FILE *fp;
	if ((fp = fopen("map.txt", "w")) == NULL)
	{
		printf("the file can not open...");
		exit(0);
	}
	for (i = 1; i <= count; i++)
		for (j = 1; j <= count; j++)
		{
			fprintf(fp, "%d", Map_M[i][j]);
			fprintf(fp, "\n");
		}
	fclose(fp);

	///将速度-时间存入文件中"map_speed.txt
	if ((fp = fopen("map_speed.txt", "w")) == NULL)
	{
		printf("the file can not open...");
		exit(0);
	}
	for (i = 1; i <= count; i++)
		for (j = 1; j <= count; j++)
		{
			fprintf(fp, "%lf", Map_Time[i][j]);
			fprintf(fp, "\n");
		}
	fclose(fp);
	///将顶点的个数存入文件
	if ((fp = fopen("count.txt", "w")) == NULL)
	{
		printf("the file can not open...");
		exit(0);
	}
	fprintf(fp, "%d", count);
	fclose(fp);

	//将票价存入文件
	if ((fp = fopen("map_money.txt", "w")) == NULL)
	{
		printf("the file can not open...");
		exit(0);
	}
	for (i = 1; i <= count; i++)
		for (j = 1; j <= count; j++)
		{
			fprintf(fp, "%lf", Map_Money[i][j]);
			fprintf(fp, "\n");
		}
	fclose(fp);
	free(E);
	Floyd(Map_M, Map_Time, Map_Money,count);
}

void PrintfMap()
{
	int i, j;
	FILE *fp;
	int count = 0;
	if ((fp = fopen("count.txt", "r")) == NULL)
	{
		printf("File open failed!\n");
		exit(0);
	}
	fscanf(fp, "%d", &count);
	fclose(fp);

	printf("顶点个数 == %d\n", count);
	printf("\n");
	if (count == 0)
	{
		printf("\n信息读入错误!!\n错误原因:没有已保存的地图,请选择重新输入地图信息!!\n");
		return;
	}
	//读入文档map.txt
	if ((fp = fopen("map.txt", "r")) == NULL)
	{
		printf("File open failed!\n");
		exit(0);
	}
	for (i = 1; i <= count; i++)
		for (j = 1; j <= count; j++)
		{
			fscanf(fp, "%d", &Map_M[i][j]);
		}
	fclose(fp);
	printf("地图信息如下图所示:\n");
	printf("\n ");
	for (j = 1; j <= count; j++)
		printf("  %d", j);
	printf("\n");
	for (i = 1; i <= count; i++)
	{
		printf("%d  ", i);

		for (j = 1; j <= count; j++)
		{

			if (Map_M[i][j] == INF)
				printf("   ");
			else {
				if (Map_M[i][j] < 10)
					printf("%d  ", Map_M[i][j]);
				else
					printf("%d ", Map_M[i][j]);
			}
		}
		printf("\n");
	}
}

//佛洛依德算法
void Floyd(int(*e)[Max_Num], double(*t)[Max_Num], double(*m)[Max_Num], int n)
{
	int start, end; //起始位置,终点
	//初始化记录路径详细信息数组path
	int i, j;
	//初始化终点
	for (i = 0; i <= n; i++)
		for (j = 0; j <= n; j++)
		{
			Path_Length[i][j] = j;
			Path_Time[i][j] = j;
			Path_Money[i][j] = j;
		}

	while (1)
	{
		printf("\n请输入要查询路径起点、终点位置:");
		scanf("%d %d", &start, &end);
		if (start > n || end > n)
		{
			printf("\n出现错误!!!\n错误原因:输入了不存在的顶点!!\n请重新输入!!\n");
			printf("\n顶点个数为:%d", n);
			continue;
		}
		int Floyd_xuanze = 0;
		printf("\n请输入查询方式:\n");
		printf("1---最短路径\n");
		printf("2---最短时间\n");
		printf("3---最便宜\n");
		scanf("%d", &Floyd_xuanze);
		switch (Floyd_xuanze)
		{
		case 1: Floyd_Length(e, n, start, end); break;
		case 2: Floyd_Time(t, n, start, end); break;
		case 3: Floyd_Money(m, n, start, end); break;
		default: printf("请输入正确指令!!!\n"); break;
		}
		int temp = 0;
		printf("是否继续查询:yes:1 / no:0\n");
		scanf("%d", &temp);
		if (!temp)
			break;
	}

}
void Floyd_Length(int(*e)[Max_Num], int n, int start, int end)
{
	int k, i, j;
	///佛洛依德算法---距离
	for (k = 1; k <= n; k++)
		for (i = 1; i <= n; i++)
			for (j = 1; j <= n; j++)
				if (e[i][j] > e[i][k] + e[k][j])
				{
					e[i][j] = e[i][k] + e[k][j];
					Path_Length[i][j] = Path_Length[i][k];
				}

	///打印出最短路径及相应路径信息--距离
	printf("\n查询成功!!信息如下:\n\n");
	printf("%d=>%d:\nLength:%d km ", start, end, e[start][end]);
	int v = Path_Length[start][end];
	printf("\nPath:%d", start);
	while (v != end)
	{
		printf("->%d", v);
		v = Path_Length[v][end];
	}
	printf("->%d", end);
	printf("\n___________________________________________\n");
	printf("\n");
}
void Floyd_Time(double(*t)[Max_Num], int n, int start, int end)
{
	int k, i, j;

	///佛洛依德算法---时间
	for (k = 1; k <= n; k++)
		for (i = 1; i <= n; i++)
			for (j = 1; j <= n; j++)
				if (t[i][j] > t[i][k] + t[k][j])
				{
					t[i][j] = t[i][k] + t[k][j];
					Path_Time[i][j] = Path_Time[i][k];
				}
	///打印出最短路径及相应路径信息--距离
	printf("\n查询成功!!信息如下:\n\n");
	printf("%d=>%d:\nTime:%.2f h", start, end, t[start][end]);
	int v = Path_Time[start][end];
	printf("\nPath:%d", start);
	while (v != end)
	{
		printf("->%d", v);
		v = Path_Time[v][end];
	}
	printf("->%d", end);
	printf("\n___________________________________________\n");
	printf("\n");
}


void Floyd_Money(double(*m)[Max_Num], int n, int start, int end)
{
	int k, i, j;

	///佛洛依德算法---票价
	for (k = 1; k <= n; k++)
		for (i = 1; i <= n; i++)
			for (j = 1; j <= n; j++)
				if (m[i][j] > m[i][k] + m[k][j])
				{
					m[i][j] = m[i][k] + m[k][j];
					Path_Money[i][j] = Path_Money[i][k];
				}
	///打印出最短路径及相应路径信息--票价
	printf("\n查询成功!!信息如下:\n\n");
	printf("%d=>%d:\nMoney:%.2f yuan ", start, end, m[start][end]);
	int v = Path_Money[start][end];
	printf("\nPath:%d", start);
	while (v != end)
	{
		printf("->%d", v);
		v = Path_Money[v][end];
	}
	printf("->%d", end);
	printf("\n___________________________________________\n");
	printf("\n");
}

猜你喜欢

转载自blog.csdn.net/qq_42852559/article/details/106333752