1.题目分析

1.1题目简介

  假设你为快递公司设计快递投递路线优化程序。(1)每个市有个中转分发点,有些城市之间有直通路线,有些城市之间没有直通路线;(2)城市与城市之间的运费计算公式为:距离*1;(3)设投递包裹的尺寸、重量都一样,每条运输线路有个运力上限(即只能运输多少个包裹)。
  要求:(1)随机产生当天的包裹投递需求;(2)对所产生的包裹需求,生成运输路线策略。(3)(拓展要求):根据随机测试结果,利用程序优化城市间包裹线路。

1.2分析思路

  由上述的题目简介可知,在本次课程设计中,我们主要解决的有以下几个问题。第一个为城市矩阵的随机生成。第二个问题为最短运费的路径选择问题。第三个问题为程序优化问题。
  针对于第一个问题,采用rand()随机函数调用vs中的随机矩阵来生成所需要的距离矩阵,包裹矩阵和运力矩阵。虽然rand()函数并不能实现真正意义上的随机,但为了方便后续的调试和优化,所以没有选择加入时间因素的srand()函数。针对第二个问题,由于是选择最短运费,理论上是与Dijkstra算法的最短路径求解的原理是一样的。我们知道,Dijkstra算法是把点与点之间的最短路径作为迭代的初始数据的,而我们要求解整体的最小运费,可以将点于点之间的最小运费作为迭代的初始数据,而局部最小运费的总和就是整体路径最小运费的结果。针对于第三个问题,由于第一步采用rand()函数,所以每一次产生的矩阵都是一样的,所以在后期的调试优化中,我们通过对于同一个点到不同点的运费路径选择以及不同点到同一个点的运费路径选择,实时调整优化程序,使得程序达到最优。

2.总体设计

  基于上面的题目分析,所以在本次设计中,总结系统框架如下图所示。

图1 系统框架

  在图形用户界面通过制表符等是的界面美观简洁。在输入输出方面,采用cin,cout等来实现人机交互。通过do while()等来实现循环输入和反复查询。通过对于原本的Dijkstra算法进行调整修改来实现其对于最小运费的求解。

3.数据结构设计

  针对这一模拟系统,需要管理的数据主要有城市集合,城市间距离矩阵,城市间运力矩阵,城市间包裹矩阵等数据结构。现就每种数据给出详细的分析。

3.1城市集合

  各个城市之间处于对等状态,所以这里采用顺序结构一维数组来存储城市的名称信息。CityName定义如下。

char CityName[N] = { 'a','b','c','d','e','f','g','h','i','j' };

3.2城市间矩阵集合

  各个城市间的距离,运力,包裹运输处于一种多对多的模式,所以这里采用图的形式来存储城市间的运输信息。通过邻接矩阵来存储不同路径上的信息。由于a到b之间的距离,运力与b到a之间的距离运力完全相同。所以该图为无向图。Graph定义如下。

typedef struct graph {int vCnt;//顶点个数int adjMatrix[N][N];int CPower[N][N];//运力上限int CPackage[N][N];//包裹矩阵
}Graph;

4.算法设计

  整体算法的基本工作流程如下图所示。

图2 算法基本工作流程图

  在重复查询方面,采用了do while()循环特有的性质,通过设置标志位来实现反复查询,具体代码如下所示。

 do
{CityFirst = getchar();if (CityFirst >= 'a'&&CityFirst <= cc){cout << "第一个城市输入正确!\n";getchar();flag = 0;}else{cout << "输入有误!请重新输入!\n";getchar();flag = 1;}
} while (flag);

  而在Dijkstra算法方面,把算法中迭代的距离值替换成运费。而运费的计算公式如下。

  其中m是运费,t是趟数,即当前路径上的运力与包裹的一个比值,s是两个城市之间的距离,趟数的计算公式如下所示。

  其中p是从起始城市到目标城市的包裹值,x是当前路径上的运力上限。由于在程序中t、p和x都是整型变量,所以在算式后加1来拟合结果。而0.0001是消除由于拟合导致的p与x相等所带来的误差。经最大差值计算,0.0001对于本算法产生的影响在误差允许的范围内。具体代码如下。

dist[i] = g->adjMatrix[v][i]*(int)(g->CPackage[v][l]/(g->CPower[v][i]+0.0001)+1);

5.结果分析

  由于在本次的题目中,矩阵的运力上限与包裹对于算法的优劣性影响很大。
  所以我们定义一个数值为包裹数比运力上限大的概率。设这个数值为包运比,在本次算法中,包裹和运力都是随机生成的数据,通过运用概率论的知识,我们可以方便的求出包运比。

图3 5维矩阵示例

图4 5维矩阵a城市-e城市结果示例

  在五维矩阵,且包运比为75%时。由图三可以得到a城市到e城市要运输的包裹为8。而算法最终选择的路径为由a城市到e城市,距离为8公里,只走一趟,运费为8元。而在a城市经由b城市中转在到达c城市虽然只需要6公里,但由于运力上限的原因,需要两趟才能完成运输任务,这样运费需要12元。由此可知,该算法符合题目要求。

图5 10维矩阵示例

图6 10维矩阵b城市-e城市结果示例

  在十维矩阵,且包运比为100%时。由图四可以得到a城市到e城市要运输的包裹为14。而算法选择的路径为b-a-i-e。该路径的距离为8公里,需要趟数为5,所需运费为40元。经分析该算法符合题目要求。

6.结论

  从模拟的结果来看,本课程设计的算法完全符合题目要求。在多次的测试中由该算法输出的最优路径都是当前情况下的最小运费。平且在包运比不同的情况下,该算法总是可以选择出当前情况下的最优路径。而在用户界面方面,设置了循环输入来检验输入的城市是否满足条件。并且设置了反复查询机制,可以对于同一个城市矩阵实现对此查询,具有良好的人机交互性。
  但本算法在运输过程中认为同一次运输任务的包裹都必须要经过同一最优路径运输。在某种情况下,限制了运输的机制,后续仍有待完善。并且在城市矩阵设置方面,默认为由a城市到b城市的距离与b城市到a城市的距离相等,即为无向图,而现实生活中情况可能更为复杂,后续可以根据具体需要做出具体调整。

7.附录

整体代码

#include <iostream>
#include <stdio.h>using namespace std;//初始化认为10个城市为最大值
#define N 10
#define maxValue 10
int CityPath[N][N]; //定义最大为10×10的矩阵
int CityPower[N][N]; //定义运力上限矩阵
int CityPackage[N][N]; //定义为包裹运输矩阵
char CityName[N] = { 'a','b','c','d','e','f','g','h','i','j' };typedef struct graph {int vCnt;//顶点个数int adjMatrix[N][N];int CPower[N][N];//运力上限int CPackage[N][N];//包裹矩阵
}Graph;//Dijkstra算法
void Dijkstra(Graph *g, char first,char last) //v为起点 k为终点;
{int v,l;switch (first){case 'a':v = 0; break;case 'b':v = 1; break;case 'c':v = 2; break;case 'd':v = 3; break;case 'e':v = 4; break;case 'f':v = 5; break;case 'g':v = 6; break;case 'h':v = 7; break;case 'i':v = 8; break;case 'j':v = 9; break;}switch (last){case 'a':l = 0; break;case 'b':l = 1; break;case 'c':l = 2; break;case 'd':l = 3; break;case 'e':l = 4; break;case 'f':l = 5; break;case 'g':l = 6; break;case 'h':l = 7; break;case 'i':l = 8; break;case 'j':l = 9; break;}int *dist, *s, **path, *plen;int i, j, w, m, p;//path用来记录从v到各点的最短路径path = (int**)malloc(sizeof(int*) *g->vCnt);for (i = 0; i < g->vCnt; i++){path[i] = (int*)malloc(sizeof(int)*g->vCnt);}//s,dist,plen都为一维辅助数组 大小为顶点个数大小//s[i]=1表示第i个顶点已经求出最短路径s = (int*)malloc(sizeof(int)*g->vCnt);//dist[i]表示从v到i个顶点的距离dist = (int*)malloc(sizeof(int)*g->vCnt);//plen[i]表示从v到第i个顶点的顶点数plen = (int*)malloc(sizeof(int)*g->vCnt);for (i = 0; i < g->vCnt; i++){if (i == v){s[i] = 1;}else{s[i] = 0;}plen[i] = 0;dist[i] = g->adjMatrix[v][i]; //对dist数组初始化 if (dist[i] < maxValue&&i != v){path[i][0] = v;path[i][1] = i;plen[i] = 2;}}//逐次求出v到其余顶点的最短路径for (i = 1; i < g->vCnt - 1; i++){m = v;w = maxValue;for (j = 0; j < g->vCnt; j++){//s[j]=0表示第j个点的最短路径还没有求出并且dist[j]小于最大值//遍历与v邻接的所有顶点 选出与v距离最短的顶点mif (s[j] == 0 && dist[j] < w){//修改最大值w = dist[j];//修改顶点m = j;}}//将找出的第一个最短路径m的s[m]置为1if (m != v){s[m] = 1;}else{break;}for (j = 0; j < g->vCnt; j++){//j对应的顶点的最短路径没有被找到//并且从v到m的距离dist[m]+m到其他点的距离小于v到其他点的距离dist[j]//此时进入循环查找最短路径if (s[j] == 0 && dist[m] + g->adjMatrix[m][j] < dist[j]){dist[j] = dist[m] + g->adjMatrix[m][j];for (p = 0; p < plen[m]; p++){path[j][p] = path[m][p];}path[j][p] = j;plen[j] = plen[m] + 1;}}}输出v到所有顶点的最短路径//for (i = 0; i < g->vCnt; i++)//{// for (j = 0; j < plen[i]; j++)//   {//     printf("%d", path[i][j]);//   }// cout << "\n";//}//输出v到指定顶点的路径printf("从%c城市到%c城市需要运输的包裹数目为:%d\n", v + 97, l + 97, g->CPackage[v][l]);printf("从%c城市到%c城市的最优路径为:\n", v+97, l+97);for (j = 0; j < plen[l]; j++){if (j == plen[l] - 1){printf("%c城市", path[l][j] + 97);}else{printf("%c城市->", path[l][j] + 97);}      }printf("\n从%c城市到%c城市的距离为:%d公里\n", v + 97, l + 97, dist[l]);printf("该路径的运费为:\n城市间距离*包裹数=总运费\n%d*%d=%d\n", dist[l], g->CPackage[v][l], dist[l] * g->CPackage[v][l]);printf("总运费为%d元!", dist[l] * g->CPackage[v][l]);
}int main()
{int city;cout << "\n\t\t\t\t******************************************\n";cout << "\t\t\t\t\t基于无向图的城市间快递派送算法\n\t\t\t\t\t编写者:韩成功\n\t\t\t\t\t地点:江苏徐州\n\t\t\t\t\t时间:2020年11月";cout << "\n\t\t\t\t******************************************\n";cout << "\n请输入城市总数,并使总数小于" << N << ":";cin >> city;while (city > N){cout << "请重新输入城市总数:";cin >> city;}cout << "城市总数为:" << city << endl;//初始化路径矩阵和运力矩阵for (int i = 0; i < city; i++){for (int j = i + 1; j < city; j++){if (i == j){CityPath[i][j] = 0;CityPower[i][j] = 0;}else{//归一化城市之间的距离为0-9CityPath[i][j] = rand() % 10;CityPower[i][j] = rand() % 5 + 5;}CityPath[j][i] = CityPath[i][j];CityPower[j][i] = CityPower[i][j];}}//初始化包裹矩阵for (int i = 0; i < city; i++){for (int j = 0 ; j < city; j++){if (i == j){CityPackage[i][j] = 0;}else{CityPackage[i][j] = rand() % 10 + 5;}}}//输出矩阵cout << "城市之间的路径矩阵如下:\n\t";for (int i = 0; i < city; i++){cout <<CityName[i]<< "\t";}cout << "\n";for (int i = 0; i < city; i++){cout << CityName[i]<< "\t";for (int j = 0; j < city; j++){cout << CityPath[i][j] << "\t";}cout << "\n";}cout << "城市之间的运力上线矩阵如下:\n\t";for (int i = 0; i < city; i++){cout << CityName[i] << "\t";}cout << "\n";for (int i = 0; i < city; i++){cout << CityName[i] << "\t";for (int j = 0; j < city; j++){cout << CityPower[i][j] << "\t";}cout << "\n";}cout << "城市之间的包裹运输矩阵如下:\n\t";for (int i = 0; i < city; i++){cout << CityName[i] << "\t";}cout << "\n";for (int i = 0; i < city; i++){cout << CityName[i] << "\t";for (int j = 0; j < city; j++){cout << CityPackage[i][j] << "\t";}cout << "\n";}//初始化图Graph* CityWord=(Graph *)malloc(sizeof(Graph));CityWord->vCnt = city;//CityWord->adjMatrix[N][N] = CityPath[N][N];for (int i = 0; i < N; i++){for (int j = 0; j < N; j++){CityWord->adjMatrix[i][j] = CityPath[i][j];CityWord->CPower[i][j] = CityPower[i][j];CityWord->CPackage[i][j] = CityPackage[i][j];}}int ever = 1;while (ever){char CityFirst, CityLast;cout << "本次算法涉及到的有以下城市:\n";for (int i = 0; i < city; i++){cout << CityName[i] << " ";}cout << "\n请输入您想要查询的城市包裹派送路线:\n";cout << "查询a到b城市的派送路线\n输入示例为:a b \n";getchar(); //把回车吃掉int flag = 1;char cc=CityName[city-1];do{CityFirst = getchar();if (CityFirst >= 'a'&&CityFirst <= cc){cout << "第一个城市输入正确!\n";getchar();flag = 0;}else{cout << "输入有误!请重新输入!\n";getchar();flag = 1;}} while (flag);do{CityLast = getchar();if (CityLast >= 'a'&&CityLast <= cc&&CityLast != CityFirst){cout << "第二个城市输入正确!\n";getchar();flag = 0;}else{cout << "输入有误!请重新输入!\n";getchar();flag = 1;}} while (flag);Dijkstra(CityWord, CityFirst, CityLast);cout << "\n输入Y/y继续查询,输入N/n退出查询!";char s;do{s = getchar();if (s == 'Y' || s == 'y'){ever = 1;flag = 0;}else if (s == 'N' || s == 'n'){ever = 0;flag = 0;}else{cout << "输入有误! 请重新输入!\n";flag = 1;}} while (flag);        }cout << "查询结束,感谢使用!";return 0;
}

后续修改整理

基于无向图的城市间快递派送算法相关推荐

  1. 城市间紧急救援(Dijkstra算法)

    作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上.当其他城市有紧急求 ...

  2. python模型预测控制_【模型工具】耦合python和 SWMM的城市排水系统模型预测算法...

    美国环境署EPA开发的SWMM模型具有开源性,这使其成为最为广泛使用的城市排水系统模型.但是SWMM是基于C语言开发的,二次开发困难较大.因此本文作者利用开源的PYSWMM程序包,利用python实现 ...

  3. L2-001 城市间紧急救援 (25分)(迪杰斯特拉算法)

    L2-001 城市间紧急救援 (25分)(迪杰斯特拉算法) 作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一 ...

  4. 7-1 城市间紧急救援 (25 分)(最短路径:斯特拉算法)

    7-1 城市间紧急救援 (25 分) 作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道 ...

  5. arcgis交通可达性分析步骤_【规划广角】街道慢行品质的多维度评价与导控策略——基于多源城市数据的整合分析...

    欢迎点击以上蓝色字体 关注规划师杂志 作者苏州规划设计研究院交通所所长.同济大学建筑与城市规划学院博士研究生樊钧,同济大学建筑与城市规划学院硕士研究生唐皓明,同济大学建筑与城市规划学院助理教授.硕士生 ...

  6. 旅游规划pta(无向图求顶点间最短路径)

    关于求图的顶点间最短路径问题,基本分为两种算法: Dijkstra算法 Floyd算法 Dijkstra算法是用来求图中某个源点到其他顶点的最短路径的,而Floyd是用来求图中任意两个顶点间的最短路径 ...

  7. 基于Java毕业设计城市公交系统源码+系统+mysql+lw文档+部署软件

    基于Java毕业设计城市公交系统源码+系统+mysql+lw文档+部署软件 基于Java毕业设计城市公交系统源码+系统+mysql+lw文档+部署软件 本源码技术栈: 项目架构:B/S架构 开发语言: ...

  8. 5-35 城市间紧急救援 (25分)

    5-35 城市间紧急救援 (25分) 作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道 ...

  9. 【K-Means】基于经纬度的城市聚类

    文章目录 1. 项目准备 1.1. 问题导入 1.2. 数据集简介 2. K-Means算法 2.1. 算法特点 2.2. 算法流程 2.3. 算法缺陷 2.4. 算法改进 3. 实验步骤 3.1. ...

最新文章

  1. 软件工程--项目开发计划
  2. java中自造类是什么意思_JAVA问题,什么时候需要,Class类型的?
  3. Blazor University (9)组件 — 代码生成 HTML 属性
  4. javaone_JavaOne 2016 Essentials:您不应该错过的7个事件和会话
  5. 什么是地址译码 理解二进制编码
  6. 在电脑上显示未知发布者怎么办_电脑提示未知发布者 - 卡饭网
  7. 送女朋友的java小程序_用C编写一个送给女朋友的情人节小程序 可爱!
  8. Selenium碰到的异常记录
  9. MySql表空间的概念
  10. WAP网站制作(WAP网站建设)全攻略教程一
  11. IO基础操作(文件)
  12. java获取本月最后一天
  13. jvm-虚拟机栈笔记【详细】
  14. rs485数据线接反_RS485引脚说明及接口说明
  15. 【C/C++学习】之STL详解
  16. 多波次导弹发射中的规划问题(二)
  17. 基于PHP+MySQL的高校实验室预约管理系统
  18. 线段树 hdu3265 Posters
  19. 苹果A系列芯片的三年AI进化:为何要大规模升级AI算力?
  20. 手机沙盒隔离软件_虚拟隔离沙箱|隔离沙箱(BufferZone Pro)下载 v4.07 免费版 - 121下载站...

热门文章

  1. 二分图的完全匹配---KM算法
  2. 使用计算机打印汉字文档的是汉字,全国计算机等级考试模拟试题
  3. 扎克伯格的6大创业思维、32个商业忠告!若能悟透,赚钱不难
  4. 用DOSBox0.74进行汇编代码的运行
  5. RGB和HSV区别与互相转换
  6. Visual Studio2017专业版和企业版密钥
  7. mysql share nothing_分布式数据库的Share Nothing / Share Disk / Share Storage
  8. win7 家庭版升级旗舰版
  9. 算法 PK 猫咪 | 章鱼保罗后继竟然是只猫?
  10. 电商项目1、后端环境搭建