目录
问题:
代码1(这是题目给的代码)
解析:
功能1:
功能2:
代码
代码2(自己写的)
前言
整体思路及运行情况
代码
问题:
背景知识:图的存储、遍历及其应用,图的最短路径等。
目的要求:
掌握图的存储、构建、搜索等操作和应用,能用最短路径及其搜索等算法编制较综合性的程序,求解最优路线问题,进行程序设计、数据结构和算法设计等方面的综合训练。
实验内容:
1.任务:设计一个城市交通咨询模拟系统,利用该系统实现至少两种最优决策:最短路程到达、最省时到达等线路规划。
2.内容:
用户驾车出行由于出行目的的不同对道路路线选择的要求也有不同。例如,有的希望在途中的路程尽可能短,有的则可能希望路程中时间最短。为了能满足广大旅客的需求,编制一个城市交通咨询模拟系统,选取城市部分位置、道路抽象为程序所需要图的顶点和边,并以城市道路长度(路程),道路的某时段的速度等信息作为图结点中的弧信息,为旅客提供这两种最优决策的交通咨询。
实验说明:
1.输入和输出:
(1)输入形式:
- 构建图时,输入顶点、弧涉及的信息,包括:起始地、目的地、长度、该弧此时间段的平均速度等信息;
- 用户或者客户要输入出发地和目的地,并选择何种最优决策的路线规划。
(2)输出形式:根据用户需求输出对应信息
- 输出最短路程所需要的路线信息和最短路程;
- 输出最短时间所需要的路线信息和最短时间。
2.实验要求:
-
- 实现一个简单的交互式界面,包括系统菜单、清晰的输入提示等。
- 根据输入的交通图数据,以图形化形式把交通图显示在屏幕上。
- 以图形化形式把最优路线显示在屏幕上。
解析:
这个是实验指导书上的源码,挺好用
功能1:
首先建立三个文本文件
count文件里面存的地方的个数,map文件里面存的是一个点到另一个点的距离,map_speed文件里面存的是 一个点到另一个点的时间
看map里面的1,处于第1行第2列,就是第一个点到第二个点的距离是1,
map_speed的1.1就是第1个点到第2个点的花费的时间是1.1
这是我用的测试点
下面正式开始测试,首先你要改一下代码中的文件的路径,
运行结果图
我们可以根据之前的测试图,可以看到它的路线
功能2:
录入路线
把代码中的写入的路径更改一下
这个输入的是两个点是双向都可以通的,点1到点2 的距离是1速度是1,
思路:很简单,就是用弗罗伊德算法,计算出权值最小的路径,顺便用记录中间的一些中转点,在最后的输出路径中输出出来。
弗罗里达算法思想,想具体知道弗罗里达算法算法自己在网上搜一下吧看吧。
代码
稍微加了一些注释,这个给的代码很简单,应该不用多说吧,不会真的有人看不懂吧
#include <stdio.h> #include <stdlib.h> #define inf 99999999 #define max_element 50 int e[max_element][max_element]; //保存地图的数组 int path_e[max_element][max_element], path_t[max_element][max_element];//转折点的路径 double t[max_element][max_element]; //保存地图的速度 void Menu(); void Old_Map(); void New_Map(); void Floyd(int (*e)[max_element],double (*t)[max_element], int n); //计算最短路径 void Floyd_dist(int (*e)[max_element], int n, int start, int end); void Floyd_time(double (*e)[max_element], int n, int start, int end); 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: system("cls");break; default:printf("\n请输入正确指令!!!");break; } Menu(); } printf("\n成功退出!"); return 0; } void Menu() { printf("\n ---选择使用已保存的地图:1---"); printf("\n\n ---选择重新录入地图信息:2---\n"); printf("\n -----------清屏:3-----------\n"); printf("\n -------------退出:0-------------\n"); } //使用原有地图 void Old_Map() { int i, j; FILE *fp; int count = 0; //读入文档count.txt if((fp=fopen("C:\\Users\\jin\\Desktop\\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("C:\\Users\\jin\\Desktop\\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", &e[i][j]); }//读入距离地图,是一个矩阵 fclose(fp); ///读入文档map_speed.txt if((fp=fopen("C:\\Users\\jin\\Desktop\\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", &t[i][j]); }//读入时间地图,矩阵 fclose(fp); ///将地图信息打印*************能否采用图形界面将位置信息打印? Floyd(e,t, count); } //新录入地图 void New_Map() { //map数组初始化 int i, j; for(i = 0; i < max_element; i++ ) for(j = 0; j < max_element; j++) if(i == j) { e[i][j] = 0; t[i][j] = 0; } else { e[i][j] = inf; t[i][j] = inf; } printf("\n请输入每条路的起点、终点、路的长度、速度\n(中间以空格隔开,按下Ctrl+Z结束输入):\n"); int s, ee, l, speed; int count = 0; //地图写入 while(scanf("%d %d %d %d", &s, &ee, &l,&speed) != EOF) {//开始地,目标地,距离,速度 e[s][ee] = l; e[ee][s] = l; t[s][ee] = (l*1.0)/speed; t[ee][s] = (l*1.0)/speed; printf("%.2f ", t[s][ee]); count++; } ///将地图存入文件map.txt FILE *fp; if((fp=fopen("C:\\Users\\jin\\Desktop\\map1.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", e[i][j]); fprintf(fp,"\n"); } fclose(fp); ///将速度-时间存入文件中"map_speed.txt if((fp=fopen("C:\\Users\\jin\\Desktop\\map_speed1.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", t[i][j]); fprintf(fp,"\n"); }//像文件里面写入速度(浮点数) fclose(fp); ///将顶点的个数存入文件 if((fp=fopen("C:\\Users\\jin\\Desktop\\count1.txt","w")) == NULL) { printf("the file can not open..."); exit(0); } fprintf(fp,"%d", count); fclose(fp); Floyd(e,t, count); } //佛洛依德算法 void Floyd(int (*e)[max_element],double (*t)[max_element],int n) { int start, end; //起始位置,终点 //初始化记录路径详细信息数组path int i, j; //初始化终点*** for( i = 0; i <= n; i++) for(j = 0; j <= n; j++) { path_e[i][j] = j; path_t[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"); scanf("%d", &Floyd_xuanze); /** *异常处理 */ switch(Floyd_xuanze) { case 1: Floyd_dist(e, n, start, end);break; case 2: Floyd_time(t,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_dist(int (*e)[max_element], 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_e[i][j] = path_e[i][k];//记录中转点 } ///打印出最短路径及相应路径信息--距离 printf("\n查询成功!!信息如下:\n\n"); printf("%d=>%d, length:%d, ",start, end, e[start][end]); int v = path_e[start][end];//最开始的中转点 printf("path:%d", start); while(v!=end) { printf("->%d",v); v = path_e[v][end]; } printf("->%d", end); printf("\n___________________________________________\n"); } void Floyd_time(double (*t)[max_element], 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_t[i][j] = path_t[i][k]; } ///打印出最短路径及相应路径信息--距离 printf("\n查询成功!!信息如下:\n\n"); printf("%d=>%d, time:%.2fh, ",start, end, t[start][end]); int v = path_t[start][end]; printf("path:%d", start); while(v!=end) { printf("->%d",v); v = path_t[v][end]; } printf("->%d", end); printf("\n___________________________________________\n"); }代码2(自己写的)
前言
如果你这个看的不是很懂,建议看第一个,
其实也没啥,就是实现一个中文的地点,用map容器进行映射。
其中的难点就是搞了我好久的一个小东西,读取文件,一个词,一个词的读取,搞得我很头疼,不过最后巧妙的解决啦
这个东西如果只用getline(ifs, read, ' '),读取文件的时候,当读取到第一行最后一个词的时候,会和第二行第一个词一起读,于是乎,可能应该搞了有点长时间把,想了一个巧妙的办法给解决啦,唉这就是生活啊,兵来将挡,水来土掩。
整体思路及运行情况
思路:读取文件里面给的路线图,把这些点用弗罗伊德算法,算出最优解,根据所求,输出所要。
主要的亮点就是中文的地点,用了map容器进行一些替换
运行情况:
首先把你的文件调整成ANSI编码,
在文件的输入格式是,开始地名,目的地名,距离(浮点型),速度(浮点型)
这是我的地图,画了一下
开始运行,首先你要知道你的文件的路径
代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; map<string,int> pp; map<int,string> qq; #define inf 99999999 double dist[50][50],timee[50][50]; int locations = 0; void Floyd(double mn[50][50],int choose); void Choose(); void Floyd(double mn[50][50],int choose) { int path_min[50][50];//记录中间转折点 for(int i=1; i<=locations; i++) for(int j=1; j<=locations; j++) if(i!=j&&mn[i][j]==0) { mn[i][j] = inf;//初始化地图 //cout<<dist[i][j]<<endl; } for(int i=1; i<=locations; i++) for(int j=1; j<=locations; j++) { path_min[i][j] = j;//初始化转折点 } //弗罗里达算法 for(int k = 1; k<=locations; k++) for(int i=1; i<=locations; i++) for(int j=1; j<=locations; j++) { if(mn[i][j]>mn[i][k]+mn[k][j]) { mn[i][j] = mn[i][k]+mn[k][j]; path_min[i][j] = path_min[i][k]; } } while(1) { printf("请输入出发地名和目的地名\n"); printf("出发地名:"); string ss; cin>>ss; int st = pp[ss]; printf("目的地名:"); string sss; cin>>sss; int ed = pp[sss]; cout<<"++++++++++++++++++++++++"<<endl; cout<<(choose == 1 ? "您所需的最短路程为:":"最短时间为:"); cout<<mn[st][ed]; cout<<(choose == 1 ? "公里" : "小时")<<endl; cout<<"++++++++++++++++++++++++"<<endl; cout<<"您的路线为:"<<endl; cout<<"------------------------"<<endl; cout<<ss<<"->"; int v = path_min[st][ed]; while(v!=ed) { cout<<qq[v]<<"->"; v = path_min[v][ed]; } cout<<sss<<endl; cout<<"------------------------"<<endl; cout<<"请问是选择再次询问,还是退出,还是返回上一级"<<endl; cout<<"\t1再次询问\n"<<"\t2.返回上一级\n"<<"\t3.退出\n"<<endl; int c; cin>>c; if(c==1) {} else if(c==2) Choose(); else if(c==3) return; } } void Choose() { printf("请选择查询方式\n"); printf("1.最短路径\t"); printf("2.最短时间\t\n"); int choose; cin>>choose; if(choose==1) { Floyd(dist,choose);//最短路程 } else if(choose==2) { Floyd(timee,choose);//最少时间 } else { cout<<"您输入的指令有误,请重新输入"<<endl; Choose(); } } int main() { int id=1; cout<<"请输入您地图的位置"<<endl; string Path; cin>>Path;//输入位置 char path[100]; for(int i=0; i<Path.length(); i++) path[i] = Path[i]; ifstream ifs(path); if(ifs!=NULL) cout<<"您的地图已被打开已经被打开"<<endl; string read; int ans = 0; string start,end;//出发地,目标地 double dis,sp;//距离,速度 while(getline(ifs, read, ' ')) { if(ans%4==0)//读取的第一个词 { start = read; //cout<<"开始地"<<read<<endl; } if(ans%4==1)//读取的第二个词 { end = read; //cout<<"目标地"<<read<<endl; } if(ans%4==2)//读取的第三个词和第四个词 { char s1[10]; memset(s1,0,sizeof(s1)); for(int i=0; i<read.length(); i++) s1[i] = read[i]; dis = atof(s1); //cout<<dis<<"距离"<<read<<endl; getline(ifs, read, '\n'); char s2[10]; for(int i=0; i<read.length(); i++) s2[i] = read[i]; sp = atof(s2); // cout<<"速度"<<read<<endl; ans++; } //cin>>start>>end>>dis>>sp; if(ans%4==3)//四个读取完开始储存 { if(pp[start]==0)//如果这个地点没有被储存,便开始储存 { pp[start] = id;//地点对应的序号 qq[id] = start; id++; } if(pp[end]==0) { pp[end] = id; qq[id] = end; id++; } dist[pp[start]][pp[end]] = dis;//这段路的而距离 timee[pp[start]][pp[end]] =dis/sp;//这段路的时间 //cout<<dist[pp[start]][pp[end]]<<"--"<<timee[pp[start]][pp[end]]<<endl; } ans++; } map<string,int>::iterator it; for(it = pp.begin(); it!=pp.end(); it++) { locations++;//统计共有几个地点 //cout<<it->first<<"--"<<it->second<<endl; } /*for(int i=1; i<=5; i++) { cout<<qq[i]<<endl; }*/ //cout<<locations<<endl; Choose(); return 0; }