配送问题

  • 目录
    • 问题及数据
      • 1. 问题说明
      • 2. 测试数据和说明
      • 3. 数据
    • 思路一:贪心算法
      • 1. 原始方案
        • [1] 过程分析
        • [2] 例子分析
        • [3] 结果分析
        • [4] 案例代码
      • 2. 改进尝试A-失败(╯▔皿▔)╯
        • a. 改进点讨论
        • b.例子分析
        • c. 结果分析
        • c. 代码
      • 3. 改进尝试B-略有改进(注意:理论上貌似行不通)
        • a. 改进点讨论
        • b.例子分析
        • c. 结果分析
        • c. 代码
      • 4. 改进尝试C-在改进A中引入B的比值法
        • a. 改进点讨论
        • b. 结果分析
    • 思路二:暴力求解
      • 1.思路分析
      • 2.过程分析
      • 3.判断条件
      • 4.结果分析
      • 5.代码
    • 思路三:智能算法
      • 代码
      • 1.禁忌算法
        • (1) 禁忌算法基本思路
        • (2)禁忌算法伪代码
        • (3)禁忌算法具体实现细节
        • (4)禁忌算法算法结果
      • 2.模拟退火算法
        • (1) 模拟退火算法基本思路
        • (2)模拟退火算法伪代码
        • (3)模拟退火算法具体实现细节
        • (4)模拟退火算法算法结果
      • 3.遗传算法
        • (1) 遗传算法基本思路
        • (2)遗传算法伪代码
        • (3)遗传算法具体实现细节
        • (4)遗传算法结果
        • (5)图
      • 4.蚁群算法
        • (1) 蚁群算法基本思路
        • (2)蚁群算法伪代码
        • (3)蚁群算法具体实现细节
        • (4)蚁群算法算法结果
      • 5.节约算法

目录

算法就是探索的过程嘛~,记录问题研究过程,不专业,其中可能有些错误~还望指正!

问题及数据

1. 问题说明

通过实际案例描述,根据配送点和业务需求量,进行最优路线的计算。由物流中心点出发,配送多个客户点后再回到起点,根据车辆数量,承载限制,不同车辆服务成本、运行里程限制等条件选择最优运输路径(总里程最短),使成本最小化,配送订单最大化,满载率最大化(如由一个配送中心向各个销售点配送货物,通过算法确定配送中心每辆车的配送方案,包括配送至哪个客户,配送量,下一个配送目的地)。

2. 测试数据和说明

某物流中心有5台配送车辆,车辆的最大载重均为8T,一次配送的最大行驶距离都为50KM,需要向20个客户送货,物流中心和20个客户的坐标及其客户的需求量随机产生,其中,物流中心的坐标为(14.2KM,13.1km),要求合理安排车辆的配送路线和载重量,使配送总里程最短。

3. 数据

客户点 横坐标x(km) 横坐标x(km) 需求量q(t)
1 12.8 8.5 0.1
2 18.4 3.4 0.4
3 15.4 16.6 1.2
4 18.9 15.2 1.5
5 15.5 11.6 0.8
6 3.9 10.6 1.3
7 10.6 7.6 1.7
8 8.6 8.4 0.6
9 12.5 2.1 1.2
10 13.8 5.2 0.4
11 6.7 16.9 0.9
12 14.8 2.6 1.3
13 1.8 8.7 1.3
14 17.1 11 1.9
15 7.4 1 1.7
16 0.2 2.8 1.1
17 11.9 19.8 1.5
18 13.2 15.1 1.6
19 6.4 5.6 1.7
20 9.6 14.8 1.5

说明:各客户相互之间和物流中心与客户之间的距离均采用直线距离

思路一:贪心算法

1. 原始方案

[1] 过程分析

贪心算法其实很简单。
即每次选择距离最小的点,然后进行判断:

  1. 加入此点后,货车的剩余行驶里程能否从此点直接回到出发点。(此处可优化)
  2. 加入此点,是否造成载重不足情况。

如果都可以那么加入此点,寻找下一个距离最近的点,直到不满足条件回到出发点。
第一辆车回到出发点后,如果还存在未运输的城市,那么继续采用第二辆车以此类推,直到城市全部运输完成。

[2] 例子分析

用此方法的第一辆车做例子来讲解这个方法

计算与出发点距离最近的点,即5号点,那么进入5号点。进入完成后,再计算与5号点最近距离的点,以此类推。
计算所得:

所得路线图如图所示

[3] 结果分析

贪心算法所取得的效果并不尽人意。
从每辆车的行驶距离和载重可以看出,大部分情况下都是载重先用完。
虽然一辆车的局部是最佳的但整体来说不是最佳的。

结果如图所示:

路线图:

[4] 案例代码

#include <fstream>
#include <string>
#include <iostream>
#include <vector>
#include<math.h>
using namespace std;// 功能:将filename 中的数据(共cols列)读取到_vector中,_vector可视为二维数组
int read_scanf(const string &filename, const int &cols, vector<double *> &_vector)
{FILE *fp = fopen(filename.c_str(), "r");bool flag = true;int i = 0;if (!fp){cout << "File open error!\n";return 0;}while (flag){double *rowArray = new double[cols]; //new一个double类型的动态数组for (i = 0; i < cols; i++) //读取数据,存在_vector[cols]中{if (EOF == fscanf(fp,"%lf", &rowArray[i])){flag = false;break;}//输出rowArray存入的数据//cout << rowArray[0] << " " << rowArray[1] << " " << rowArray[2] << " " << rowArray[3] << endl;}if (cols == i) //将txt文本文件中的一行数据存入rowArray中,并将rowArray存入vector中_vector.push_back(rowArray);}fclose(fp);return 1;
}int  main()
{/*定义数据*/double data_xy[21][2];//用来记录每个点的X,Y坐标。double data_q[21];//各点重量double data_dis[21][21];//各点到各点的距离int data_fin[21]= {0}; //是否走过此点int car_num=0;//车的数量double car_km[5];double car_kg[5];int car_pa[5][21];//这辆车经过的点int carlu[5]={1,1,1,1,1};data_xy[0][0]=14.2;data_xy[0][1]=13.1;data_fin[0]=1;/*读取数据*/string file ="C:/Users/49786/Desktop/data.txt";//txt文件中有4列int columns = 4;vector<double *> output_vector;if (!read_scanf(file, columns, output_vector)){return 0;}//output_vector可视为二维数组;输出数组元素:int rows = output_vector.size();for (int i = 0; i < rows; i++){for (int j = 1; j < 4; j++){if(j!=3){data_xy[i+1][j-1]=output_vector[i][j];}else{data_q[i+1]=output_vector[i][j];}}}//cout<<data_xy[1][0]<<endl;//cout<<data_xy[1][1]<<endl;// cout<<data_q[1]<<endl;/*计算各个点之间的距离*/for(int i=0; i<21; i++){   //cout<<i<<": "<<endl;for(int j=0; j<21; j++){   //cout<<j<<"---"<<endl;//cout<<"x相减:"<<data_xy[i][0]-data_xy[j][0]<<"平方:"<<pow(data_xy[i][0]-data_xy[j][0],2)<<endl;// cout<<"y相减:"<<data_xy[i][1]-data_xy[j][1]<<"平方:"<<pow(data_xy[i][1]-data_xy[j][1],2)<<endl;//cout<<"相加开方"<<sqrt(pow(data_xy[i][0]-data_xy[j][0],2)+pow(data_xy[i][1]-data_xy[j][1],2))<<endl;data_dis[i][j]=sqrt(pow(data_xy[i][0]-data_xy[j][0],2)+pow(data_xy[i][1]-data_xy[j][1],2));}}
/*for(int i=0;i<21;i++){cout<<i<<": ";for(int j=0;j<21;j++){cout<<data_dis[i][j]<<" ";}cout<<endl;}*/for(int car=1; car<=5; car++){double km=50;//最大行驶路程double kg=8;//最大载重int di=0;//下一步要走的地点。int ki=0;//记录下一步int chong=0;//避免重复car_pa[car-1][0]=di;for(int i=0; km>=0||kg>=0; i++){double minum=100;for(int j=1; j<21;j++){if(j!=di&&data_fin[j]!=1){if(data_dis[di][j]<minum){minum=data_dis[di][j];ki=j;//cout<<"是否出现"<<data_fin[j]<<"  ";//cout<<"找出最小值下标:"<<ki<<endl;//cout<<"找出最小值:"<<minum<<endl;}}//找出最小的数值以及下表}di=ki;//cout<<"距离:"<<km-data_dis[car_pa[car-1][i]][di]<<"回去的距离:"<<data_dis[di][0]<<endl;//cout<<"如果加入那么减去的重量"<<kg-data_q[di]<<endl;if((km-data_dis[car_pa[car-1][i]][di])>=data_dis[di][0]&&(kg-data_q[di])>=0){if(chong==di){//这一步大有可为!car_pa[car-1][i+1]=0;car_km[car-1]+=data_dis[car_pa[car-1][i]][0];carlu[car-1]++;break;}car_pa[car-1][i+1]=di;//下一步设置为didata_fin[di]=1;km-=data_dis[car_pa[car-1][i]][di];kg-=data_q[di];car_km[car-1]+=data_dis[car_pa[car-1][i]][di];car_kg[car-1]+=data_q[di];chong=di;carlu[car-1]++;}else{//这一步大有可为!car_pa[car-1][i+1]=0;car_km[car-1]+=data_dis[car_pa[car-1][i]][0];carlu[car-1]++;break;}}int k=1;for(int i=1;i<21;i++){if(data_fin[i]==0){k=0;}}if(k==1)break;car_num=car_num+1;}double carallkm=0;for(int i=0;i<=car_num;i++){cout<<"第"<<i+1<<"辆车路径:";for(int j=0;j<carlu[i];j++){cout<<car_pa[i][j]<<"-";}cout<<"行驶距离:"<<car_km[i]<<endl;cout<<"载重:"<<car_kg[i]<<endl;carallkm+=car_km[i];}cout<<"总距离"<<carallkm<<endl;return 0;
}

2. 改进尝试A-失败(╯▔皿▔)╯

a. 改进点讨论

在原始方案中,过程分析的第一点提到了,车辆在最后一个城市会直接返回到原点

改进
在到达最后一个城市后,不是直接返回原点,而是挑选能够到达并且到达后还能直接回到原点的城市,载重也必须够用。
因为加入这个新城市,还能够直接跳回原点的必然是相较于贪心选择的城市离原点更近。

只要能多完成一个城市,必然可以减少下一辆车的距离。从而从从整体上优化行车的距离。

判断条件
1.到达贪心最后一个城市后不再考虑距离,只考虑加入的这个城市后在能够直接回到原点(从符合条件的点中,选择离最后一个城市最近的【值得考虑】)。
2.载重够用。

b.例子分析

以第二辆车为例子:

在第二辆车到达9点时,按照正常计算应该计算 最近的12点是否符合条件,12点 行程足够而重量不足如黄色箭头所示,按第一种方法应该直接返回出发点。
而根据改进尝试,在到达9点到12点无法达到时,将不再考虑离其最近的路程点,而是考虑剩余的行程和载重合适的点,如蓝色所示

c. 结果分析

很好 反向操作,负优化 !!!(╯▔皿▔)╯


路线图:

c. 代码

#include <fstream>
#include <string>
#include <iostream>
#include <vector>
#include<math.h>
using namespace std;// 功能:将filename 中的数据(共cols列)读取到_vector中,_vector可视为二维数组
int read_scanf(const string &filename, const int &cols, vector<double *> &_vector)
{FILE *fp = fopen(filename.c_str(), "r");bool flag = true;int i = 0;if (!fp){cout << "File open error!\n";return 0;}while (flag){double *rowArray = new double[cols]; //new一个double类型的动态数组for (i = 0; i < cols; i++) //读取数据,存在_vector[cols]中{if (EOF == fscanf(fp,"%lf", &rowArray[i])){flag = false;break;}//输出rowArray存入的数据//cout << rowArray[0] << " " << rowArray[1] << " " << rowArray[2] << " " << rowArray[3] << endl;}if (cols == i) //将txt文本文件中的一行数据存入rowArray中,并将rowArray存入vector中_vector.push_back(rowArray);}fclose(fp);return 1;
}int  main()
{/*定义数据*/double data_xy[21][2];//用来记录每个点的X,Y坐标。double data_q[21];//各点重量double data_dis[21][21];//各点到各点的距离int data_fin[21]= {0}; //是否走过此点int car_num=0;//车的数量double car_km[5];double car_kg[5];int car_pa[5][21];//这辆车经过的点int carlu[5]={1,1,1,1,1};data_xy[0][0]=14.2;data_xy[0][1]=13.1;data_fin[0]=1;/*读取数据*/string file ="C:/Users/49786/Desktop/data.txt";//txt文件中有4列int columns = 4;vector<double *> output_vector;if (!read_scanf(file, columns, output_vector)){return 0;}//output_vector可视为二维数组;输出数组元素:int rows = output_vector.size();for (int i = 0; i < rows; i++){for (int j = 1; j < 4; j++){if(j!=3){data_xy[i+1][j-1]=output_vector[i][j];}else{data_q[i+1]=output_vector[i][j];}}}//cout<<data_xy[1][0]<<endl;//cout<<data_xy[1][1]<<endl;// cout<<data_q[1]<<endl;/*计算各个点之间的距离*/for(int i=0; i<21; i++){   //cout<<i<<": "<<endl;for(int j=0; j<21; j++){   //cout<<j<<"---"<<endl;//cout<<"x相减:"<<data_xy[i][0]-data_xy[j][0]<<"平方:"<<pow(data_xy[i][0]-data_xy[j][0],2)<<endl;// cout<<"y相减:"<<data_xy[i][1]-data_xy[j][1]<<"平方:"<<pow(data_xy[i][1]-data_xy[j][1],2)<<endl;//cout<<"相加开方"<<sqrt(pow(data_xy[i][0]-data_xy[j][0],2)+pow(data_xy[i][1]-data_xy[j][1],2))<<endl;data_dis[i][j]=sqrt(pow(data_xy[i][0]-data_xy[j][0],2)+pow(data_xy[i][1]-data_xy[j][1],2));}}
/*for(int i=0;i<21;i++){cout<<i<<": ";for(int j=0;j<21;j++){cout<<data_dis[i][j]<<" ";}cout<<endl;}*/for(int car=1; car<=5; car++){double km=50;//最大行驶路程double kg=8;//最大载重int di=0;//下一步要走的地点。int ki=0;//记录下一步int chong=0;//避免重复car_pa[car-1][0]=di;for(int i=0; km>=0||kg>=0; i++){double minum=100;for(int j=1; j<21;j++){if(j!=di&&data_fin[j]!=1){if(data_dis[di][j]<minum){minum=data_dis[di][j];ki=j;//cout<<"是否出现"<<data_fin[j]<<"  ";//cout<<"找出最小值下标:"<<ki<<endl;//cout<<"找出最小值:"<<minum<<endl;}}//找出最小的数值以及下表}di=ki;//cout<<"距离:"<<km-data_dis[car_pa[car-1][i]][di]<<"回去的距离:"<<data_dis[di][0]<<endl;//cout<<"如果加入那么减去的重量"<<kg-data_q[di]<<endl;if((km-data_dis[car_pa[car-1][i]][di])>=data_dis[di][0]&&(kg-data_q[di])>=0){if(chong==di){//这一步大有可为!car_pa[car-1][i+1]=0;car_km[car-1]+=data_dis[car_pa[car-1][i]][0];carlu[car-1]++;break;}car_pa[car-1][i+1]=di;//下一步设置为didata_fin[di]=1;km-=data_dis[car_pa[car-1][i]][di];kg-=data_q[di];car_km[car-1]+=data_dis[car_pa[car-1][i]][di];car_kg[car-1]+=data_q[di];chong=di;carlu[car-1]++;}else{double minuu=100;int uj=0;//记录当前for(int u=1;u<21;u++){if(data_fin[u]!=1){if((km-data_dis[car_pa[car-1][i]][u])>=data_dis[u][0]&&(kg-data_q[u])>=0&&data_dis[u][0]<=data_dis[car_pa[car-1][i]][0]){if(data_dis[car_pa[car-1][i]][u]<minuu){minuu=data_dis[car_pa[car-1][i]][u];uj=u;}}}}if(uj!=0){car_pa[car-1][i+1]=uj;data_fin[uj]=1;km-=data_dis[car_pa[car-1][i]][uj];kg-=data_q[uj];car_km[car-1]+=data_dis[car_pa[car-1][i]][uj];car_kg[car-1]+=data_q[uj];carlu[car-1]++;}else{car_pa[car-1][i+1]=0;car_km[car-1]+=data_dis[car_pa[car-1][i]][0];carlu[car-1]++;break;}//这一步大有可为!}}int k=1;for(int i=1;i<21;i++){if(data_fin[i]==0){k=0;}}if(k==1)break;car_num=car_num+1;}double carallkm=0;for(int i=0;i<=car_num;i++){cout<<"第"<<i+1<<"辆车路径:";for(int j=0;j<carlu[i];j++){cout<<car_pa[i][j]<<"-";}cout<<"行驶距离:"<<car_km[i]<<endl;cout<<"载重:"<<car_kg[i]<<endl;carallkm+=car_km[i];}cout<<"总距离"<<carallkm<<endl;return 0;
}

3. 改进尝试B-略有改进(注意:理论上貌似行不通)

a. 改进点讨论

在原始方案中,采取了选择最小距离的办法,那么我们引入权重,用权重来进行贪心算法(距离/重量 即选取每吨重量所用最少距离的地点)

改进
将原本的距离,变成 距离/重量,即选取每吨重量所用最小千米数的地点

判断条件
1.距离与重量的比值,选取最小的。
2.载重够用。

b.例子分析

其实在每个方案的计算中,我们都会拿到每个点到达每个点之间的距离表。现在我们要引入每个点到每个点的距离与重量的比值表,拿它作为贪心的依据:

数据暂不提供。

c. 结果分析

感觉还不错,最起码下降了一点(。・∀・)ノ


路线图:

c. 代码

#include <fstream>
#include <string>
#include <iostream>
#include <vector>
#include<math.h>
using namespace std;// 功能:将filename 中的数据(共cols列)读取到_vector中,_vector可视为二维数组
int read_scanf(const string &filename, const int &cols, vector<double *> &_vector)
{FILE *fp = fopen(filename.c_str(), "r");bool flag = true;int i = 0;if (!fp){cout << "File open error!\n";return 0;}while (flag){double *rowArray = new double[cols]; //new一个double类型的动态数组for (i = 0; i < cols; i++) //读取数据,存在_vector[cols]中{if (EOF == fscanf(fp,"%lf", &rowArray[i])){flag = false;break;}//输出rowArray存入的数据//cout << rowArray[0] << " " << rowArray[1] << " " << rowArray[2] << " " << rowArray[3] << endl;}if (cols == i) //将txt文本文件中的一行数据存入rowArray中,并将rowArray存入vector中_vector.push_back(rowArray);}fclose(fp);return 1;
}int  main()
{/*定义数据*/double data_xy[21][2];//用来记录每个点的X,Y坐标。double data_q[21];//各点重量double data_dis[21][21];//各点到各点的距离double data_qz[21][21];//各点到各点的权重int data_fin[21]= {0}; //是否走过此点int car_num=0;//车的数量double car_km[5];double car_kg[5];int car_pa[5][21];//这辆车经过的点int carlu[5]={1,1,1,1,1};data_xy[0][0]=14.2;data_xy[0][1]=13.1;data_fin[0]=1;/*读取数据*/string file ="C:/Users/49786/Desktop/data.txt";//txt文件中有4列int columns = 4;vector<double *> output_vector;if (!read_scanf(file, columns, output_vector)){return 0;}//output_vector可视为二维数组;输出数组元素:int rows = output_vector.size();for (int i = 0; i < rows; i++){for (int j = 1; j < 4; j++){if(j!=3){data_xy[i+1][j-1]=output_vector[i][j];}else{data_q[i+1]=output_vector[i][j];}}}//cout<<data_xy[1][0]<<endl;//cout<<data_xy[1][1]<<endl;// cout<<data_q[1]<<endl;/*计算各个点之间的距离*/for(int i=0; i<21; i++){   //cout<<i<<": "<<endl;for(int j=0; j<21; j++){   //cout<<j<<"---"<<endl;//cout<<"x相减:"<<data_xy[i][0]-data_xy[j][0]<<"平方:"<<pow(data_xy[i][0]-data_xy[j][0],2)<<endl;// cout<<"y相减:"<<data_xy[i][1]-data_xy[j][1]<<"平方:"<<pow(data_xy[i][1]-data_xy[j][1],2)<<endl;//cout<<"相加开方"<<sqrt(pow(data_xy[i][0]-data_xy[j][0],2)+pow(data_xy[i][1]-data_xy[j][1],2))<<endl;data_dis[i][j]=sqrt(pow(data_xy[i][0]-data_xy[j][0],2)+pow(data_xy[i][1]-data_xy[j][1],2));}}for(int i=0; i<21; i++){   //cout<<i<<": "<<endl;for(int j=0; j<21; j++){   //cout<<j<<"---"<<endl;//cout<<"x相减:"<<data_xy[i][0]-data_xy[j][0]<<"平方:"<<pow(data_xy[i][0]-data_xy[j][0],2)<<endl;// cout<<"y相减:"<<data_xy[i][1]-data_xy[j][1]<<"平方:"<<pow(data_xy[i][1]-data_xy[j][1],2)<<endl;//cout<<"相加开方"<<sqrt(pow(data_xy[i][0]-data_xy[j][0],2)+pow(data_xy[i][1]-data_xy[j][1],2))<<endl;data_qz[i][j]=data_dis[i][j]/data_q[j];}}
/*for(int i=0;i<21;i++){cout<<i<<": ";for(int j=0;j<21;j++){cout<<data_dis[i][j]<<" ";}cout<<endl;}*/for(int car=1; car<=5; car++){double km=50;//最大行驶路程double kg=8;//最大载重int di=0;//下一步要走的地点。int ki=0;//记录下一步int chong=0;//避免重复car_pa[car-1][0]=di;for(int i=0; km>=0||kg>=0; i++){double minum=100;for(int j=1; j<21;j++){if(j!=di&&data_fin[j]!=1){if(data_qz[di][j]<minum){minum=data_qz[di][j];ki=j;//cout<<"是否出现"<<data_fin[j]<<"  ";//cout<<"找出最小值下标:"<<ki<<endl;//cout<<"找出最小值:"<<minum<<endl;}}//找出最小的数值以及下表}di=ki;//cout<<"距离:"<<km-data_dis[car_pa[car-1][i]][di]<<"回去的距离:"<<data_dis[di][0]<<endl;//cout<<"如果加入那么减去的重量"<<kg-data_q[di]<<endl;if((km-data_dis[car_pa[car-1][i]][di])>=data_dis[di][0]&&(kg-data_q[di])>=0){if(chong==di){//这一步大有可为!car_pa[car-1][i+1]=0;car_km[car-1]+=data_dis[car_pa[car-1][i]][0];carlu[car-1]++;break;}car_pa[car-1][i+1]=di;//下一步设置为didata_fin[di]=1;km-=data_dis[car_pa[car-1][i]][di];kg-=data_q[di];car_km[car-1]+=data_dis[car_pa[car-1][i]][di];car_kg[car-1]+=data_q[di];chong=di;carlu[car-1]++;}else{//这一步大有可为!car_pa[car-1][i+1]=0;car_km[car-1]+=data_dis[car_pa[car-1][i]][0];carlu[car-1]++;break;}}int k=1;for(int i=1;i<21;i++){if(data_fin[i]==0){k=0;}}if(k==1)break;car_num=car_num+1;}double carallkm=0;for(int i=0;i<=car_num;i++){cout<<"第"<<i+1<<"辆车路径:";for(int j=0;j<carlu[i];j++){cout<<car_pa[i][j]<<"-";}cout<<"行驶距离:"<<car_km[i]<<endl;cout<<"载重:"<<car_kg[i]<<endl;carallkm+=car_km[i];}cout<<"总距离"<<carallkm<<endl;return 0;
}

4. 改进尝试C-在改进A中引入B的比值法

a. 改进点讨论

在改进A中引入B的比值来进行路线的查找。

改进
在尝试A的基础上,将原本的距离,变成 距离/重量,即选取每吨重量所用最小千米数的地点

判断条件
1.在尝试A的基础上距离与重量的比值,选取最小的。
2.载重够用。

b. 结果分析

略逊于B方案,相较于原始改进A 略强


路线图:

c. 代码

#include <fstream>
#include <string>
#include <iostream>
#include <vector>
#include<math.h>
using namespace std;// 功能:将filename 中的数据(共cols列)读取到_vector中,_vector可视为二维数组
int read_scanf(const string &filename, const int &cols, vector<double *> &_vector)
{FILE *fp = fopen(filename.c_str(), "r");bool flag = true;int i = 0;if (!fp){cout << "File open error!\n";return 0;}while (flag){double *rowArray = new double[cols]; //new一个double类型的动态数组for (i = 0; i < cols; i++) //读取数据,存在_vector[cols]中{if (EOF == fscanf(fp,"%lf", &rowArray[i])){flag = false;break;}//输出rowArray存入的数据//cout << rowArray[0] << " " << rowArray[1] << " " << rowArray[2] << " " << rowArray[3] << endl;}if (cols == i) //将txt文本文件中的一行数据存入rowArray中,并将rowArray存入vector中_vector.push_back(rowArray);}fclose(fp);return 1;
}int  main()
{/*定义数据*/double data_xy[21][2];//用来记录每个点的X,Y坐标。double data_q[21];//各点重量double data_dis[21][21];//各点到各点的距离double data_qz[21][21];int data_fin[21]= {0}; //是否走过此点int car_num=0;//车的数量double car_km[5];double car_kg[5];int car_pa[5][21];//这辆车经过的点int carlu[5]={1,1,1,1,1};data_xy[0][0]=14.2;data_xy[0][1]=13.1;data_fin[0]=1;/*读取数据*/string file ="C:/Users/49786/Desktop/data.txt";//txt文件中有4列int columns = 4;vector<double *> output_vector;if (!read_scanf(file, columns, output_vector)){return 0;}//output_vector可视为二维数组;输出数组元素:int rows = output_vector.size();for (int i = 0; i < rows; i++){for (int j = 1; j < 4; j++){if(j!=3){data_xy[i+1][j-1]=output_vector[i][j];}else{data_q[i+1]=output_vector[i][j];}}}//cout<<data_xy[1][0]<<endl;//cout<<data_xy[1][1]<<endl;// cout<<data_q[1]<<endl;/*计算各个点之间的距离*/for(int i=0; i<21; i++){   //cout<<i<<": "<<endl;for(int j=0; j<21; j++){   //cout<<j<<"---"<<endl;//cout<<"x相减:"<<data_xy[i][0]-data_xy[j][0]<<"平方:"<<pow(data_xy[i][0]-data_xy[j][0],2)<<endl;// cout<<"y相减:"<<data_xy[i][1]-data_xy[j][1]<<"平方:"<<pow(data_xy[i][1]-data_xy[j][1],2)<<endl;//cout<<"相加开方"<<sqrt(pow(data_xy[i][0]-data_xy[j][0],2)+pow(data_xy[i][1]-data_xy[j][1],2))<<endl;data_dis[i][j]=sqrt(pow(data_xy[i][0]-data_xy[j][0],2)+pow(data_xy[i][1]-data_xy[j][1],2));}}for(int i=0; i<21; i++){   //cout<<i<<": "<<endl;for(int j=0; j<21; j++){   //cout<<j<<"---"<<endl;//cout<<"x相减:"<<data_xy[i][0]-data_xy[j][0]<<"平方:"<<pow(data_xy[i][0]-data_xy[j][0],2)<<endl;// cout<<"y相减:"<<data_xy[i][1]-data_xy[j][1]<<"平方:"<<pow(data_xy[i][1]-data_xy[j][1],2)<<endl;//cout<<"相加开方"<<sqrt(pow(data_xy[i][0]-data_xy[j][0],2)+pow(data_xy[i][1]-data_xy[j][1],2))<<endl;data_qz[i][j]=data_dis[i][j]/data_q[j];}}
/*for(int i=0;i<21;i++){cout<<i<<": ";for(int j=0;j<21;j++){cout<<data_dis[i][j]<<" ";}cout<<endl;}*/for(int car=1; car<=5; car++){double km=50;//最大行驶路程double kg=8;//最大载重int di=0;//下一步要走的地点。int ki=0;//记录下一步int chong=0;//避免重复car_pa[car-1][0]=di;for(int i=0; km>=0||kg>=0; i++){double minum=100;for(int j=1; j<21;j++){if(j!=di&&data_fin[j]!=1){if(data_qz[di][j]<minum){minum=data_qz[di][j];ki=j;//cout<<"是否出现"<<data_fin[j]<<"  ";//cout<<"找出最小值下标:"<<ki<<endl;//cout<<"找出最小值:"<<minum<<endl;}}//找出最小的数值以及下表}di=ki;//cout<<"距离:"<<km-data_dis[car_pa[car-1][i]][di]<<"回去的距离:"<<data_dis[di][0]<<endl;//cout<<"如果加入那么减去的重量"<<kg-data_q[di]<<endl;if((km-data_dis[car_pa[car-1][i]][di])>=data_dis[di][0]&&(kg-data_q[di])>=0){if(chong==di){//这一步大有可为!car_pa[car-1][i+1]=0;car_km[car-1]+=data_dis[car_pa[car-1][i]][0];carlu[car-1]++;break;}car_pa[car-1][i+1]=di;//下一步设置为didata_fin[di]=1;km-=data_dis[car_pa[car-1][i]][di];kg-=data_q[di];car_km[car-1]+=data_dis[car_pa[car-1][i]][di];car_kg[car-1]+=data_q[di];chong=di;carlu[car-1]++;}else{double minuu=100;int uj=0;//记录当前for(int u=1;u<21;u++){if(data_fin[u]!=1){if((km-data_dis[car_pa[car-1][i]][u])>=data_dis[u][0]&&(kg-data_q[u])>=0&&data_dis[u][0]<=data_dis[car_pa[car-1][i]][0]){if(data_dis[car_pa[car-1][i]][u]<minuu){minuu=data_dis[car_pa[car-1][i]][u];uj=u;}}}}if(uj!=0){car_pa[car-1][i+1]=uj;data_fin[uj]=1;km-=data_dis[car_pa[car-1][i]][uj];kg-=data_q[uj];car_km[car-1]+=data_dis[car_pa[car-1][i]][uj];car_kg[car-1]+=data_q[uj];carlu[car-1]++;}else{car_pa[car-1][i+1]=0;car_km[car-1]+=data_dis[car_pa[car-1][i]][0];carlu[car-1]++;break;}//这一步大有可为!}}int k=1;for(int i=1;i<21;i++){if(data_fin[i]==0){k=0;}}if(k==1)break;car_num=car_num+1;}double carallkm=0;for(int i=0;i<=car_num;i++){cout<<"第"<<i+1<<"辆车路径:";for(int j=0;j<carlu[i];j++){cout<<car_pa[i][j]<<"-";}cout<<"行驶距离:"<<car_km[i]<<endl;cout<<"载重:"<<car_kg[i]<<endl;carallkm+=car_km[i];}cout<<"总距离"<<carallkm<<endl;return 0;
}

思路二:暴力求解

1.思路分析

对于运输的路径,我们采取随机的方式生成,也就是将20个点随机的排列组合,然后进行计算。

整体上思路比较简单,但是需要花费的时间较多。

2.过程分析

首先会随机生成一个序列,从出发点,顺着此序列进行计算,当不满足条件时回到出发点,换下一辆车继续计算,知道路径走完或者车走完为止。

例如:

注意!!!
这张表格只是为了方便向大家展示随机生成的序列,我们每次都是随机生成一条的,并不是生成一张表格,因为这样的话,消耗太大,也没有必要。

每个序列完成后,都会记录其所需要的路程和其路径。

3.判断条件

1.加入此点后,能否直接回到出发点,如果不能那么回到出发点,换下一辆车(贪心算法原始方案相同)直到计算完成整个序列,记录其值和路径。

2.记录当前获取的总路径的最小值,如果序列在未走完时所消耗的路程已经大于当前总路径的最小值,那么直接舍弃,重新生成新的序列计算。

3.载重够用。

4.结果分析

暴力求解结果过于随机,理论上只要无限跑总能找到最优的解。

并且因为是随机生成的序列,所以理论上还是看运气。

就像下面一样两亿次还不如一亿次(╯▔皿▔)╯

下面是分别跑了 1亿次 和 2亿次的结果和路径图:

  • 1亿次得出的最小的总路径
路径:第一辆车:0-6-20-11-17-4-3-0第二辆车:0-5-1-15-19-16-13-8-0第三辆车:0-2-9-12-7-10-14-0第四辆车:0-18-0总里程:134.39KM

路径图:

  • 2亿次得出的最小的总路径
路径:第一辆车:0-18-8-6-13-11-17-0第二辆车:0-20-19-16-15-1-10-5-0第三辆车:0-4-2-12-9-7-14-0第四辆车:0-3-0总里程:138.09KM

路径图:

5.代码


思路三:智能算法

代码

https://download.csdn.net/download/jnbfknasf113/18908669?spm=1001.2014.3001.5503

1.禁忌算法

(1) 禁忌算法基本思路

1.选定一个初始解

车辆配送路径选择问题分析相关推荐

  1. Matlab车辆配送路径规划问题 各类vrp代码 带时间窗的路径规划问题

    Matlab车辆配送路径规划问题 各类vrp代码 带时间窗的路径规划问题 遗传算法 蚁群算法 模拟退火算法 混合粒子群算法解决 tsp cvrp dvrp cdvrp vrptw问题 tsp:旅行商问 ...

  2. 故障处理 软件 需求_「行业知识」地铁车辆故障智能处理分析

    摘 要:为保障地铁线路运营秩序,提高运营服务质量,降低人为因素所导致的故障的影响,必须研究地铁车辆故障智能处理系统,以适应未来地铁车辆的全自动化运行模式.基于此,笔者就地铁车辆故障智能处理进行简要分析 ...

  3. 大数据模型交易分享:运输车辆安全驾驶行为分析

    模型交易平台泰迪科技是在历史大数据与人工智能项目的沉淀基础上,以大数据挖掘建模平台为支撑,提供成熟的大数据与人工智能模型应用与项目.一方面,能够为广大企业提供成熟模型应用,解决人工模型开发周期长,难度 ...

  4. 【车辆配送】基于模拟退火 (SA)求解车辆配送 (VPR) (Matlab代码实现)

    目录 1 车辆配送问题 2 模拟退火法 3 实现结果 4 参考文献  5 Matlab代码实现 1 车辆配送问题 式(9)~( 12)中, 为配送车辆到达需求点i的时间;为需求点i到需求点j的运输成本 ...

  5. 车辆网络安全的未来(上):车辆开发中的威胁分析、风险评估和安全设计、漏洞分析

    简介 随着车辆的数字化变革,新的移动出行社会正在迎来黎明.用户所追求的便利性与不断落地的CASE(智能网联.自动化.共享和电动化)技术所提供的服务之间的差距也越来越小,下一代移动出行社会正在塑造.另一 ...

  6. matlab 汽车振动,基于MatLab的车辆振动响应幅频特性分析

    [实例简介] 利用MatLab-Simulink 仿真 了不同减振器阻尼系数和不同悬架刚度下车身加速 度.悬架动挠度.车轮动载分别对于路面速度激励振动 响应的幅频特性, 从而为半主动悬架和主动悬架的优 ...

  7. matlab振动响应,基于MatLab的车辆振动响应幅频特性分析-中原工学院学报.PDF

    22 3 Vol.22 No.3 2011 6 JOURNAL OF ZHONGYUAN UNIVERSITY OF TECH NOLOGY Jun., 2011 :1671-6906(2011)03 ...

  8. 【路径规划-VRP问题】基于模拟退火 (SA)求解车辆配送 (VPR)附Matlab代码

    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信.

  9. 【VRPTW】基于蚁群算法实现时间窗车辆配送问题附Matlab代码

    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信.

最新文章

  1. ICCV2017 | 一文详解GAN之父Ian Goodfellow 演讲《生成对抗网络的原理与应用》(附完整PPT)
  2. (0007) iOS 开发之Xcode8上传AppStore遇到的TencentOpenApi_IOS_Bundle.bundle
  3. 初学__Python——Python的基本输入输出函数
  4. Java多线程(5)--线程通信wait和notify
  5. 华为开发者被批评在 Linux 内核刷 KPI
  6. Block的引用循环问题 (ARC non-ARC)
  7. 【Spring Cloud 系列】 二、Spring Cloud Eureka 的第一印象
  8. SpringMVC中的返回值问题之三返回list类型和map类型
  9. LODOP打印项水平居中
  10. 错题集--大一C语言选择题
  11. imagemagick 压缩gif的正确姿势
  12. Respones请求重定向
  13. 一个人被提拔,不仅仅是能力,而是信任
  14. (精华)2020年10月7日 高并发高可用 Redis实现异步架构
  15. Oracle 删除数据后释放数据文件所占磁盘空间(表空间降高水位)
  16. 后缀001,002,003等的文件解压
  17. shell脚本运行报错: syntax error: unmatched ‘while‘
  18. 19. OP-TEE中TA与CA执行流程详解-------软件架构篇
  19. 智能移动机器人--科研项目汇总
  20. 机器人实践课程镜像分享及使用说明(Arduino+ROS1+ROS2+Gazebo+SLAM+...)

热门文章

  1. sdcms php版本,SDCMS产品手册
  2. JavaScript - onunload失效
  3. 微信小程序onLoad、onShow、onHide、onUnload区别
  4. 我的研究生论文的小总结 (以多标签方向为例)
  5. Excel表格中根据身份证号获取出生日期、生日、年龄、性别、工龄、退休龄
  6. 随笔:项目管理+团队管理+运维管理+开发管理
  7. Vue全家桶:路由 vue-router
  8. macOS如何修改默认打开方式
  9. 如何对软件质量进行评估
  10. Android ROOT System权限 设备管理器