(1)、任务:
设计一个城市交通咨询模拟系统,利用该系统实现至少两种最优决策:最短路程到达、最省时到达等线路规划。
(2)、内容:
用户驾车出行由于出行目的的不同对道路路线选择的要求也有不同。例如,有的希望在途中的路程尽可能短,有的则可能希望路程中时间最短。为了能满足广大旅客的需求,编制一个城市交通咨询模拟系统,选取城市部分位置、道路抽象为程序所需要图的顶点和边,并以城市道路长度(路程),道路的某时段的速度等信息作为图结点中的弧信息,为旅客提供这两种最优决策的交通咨询。
(1)、最短路径查询
(2)、最短时间查询
(3)、 最少花费查询
(4)、打印地图信息
/*
写在前面:
<1> 输入注意事项
需要输入输入每条路的起点、终点、路的长度、速度,
在输入完成后需要回车,然后键入{【Ctrl+Z】+【Enter】}*3 !!!
(编译环境VS2017)
<2> 计费规则
小于等于 2 km 的时候一律按 5 yuan收费,
大于等于 2 km 的部分按照 1 yuan/km 计费。
*/
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#define INF 99999999
#define Max_Num 50 //顶点个数最大值
typedef int WeightType;
typedef int Vertex;
typedef struct ENode *ptrToENode;
struct ENode { // 边
Vertex 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");
}