【问题说明】 |
通过实际案例描述,根据配送点和业务需求量,进行最优路线的计算。由物流中心点出发,配送多个客户点后再回到起点,根据车辆数量,承载限制,不同车辆服务成本、运行里程限制等条件选择最优运输路径(总里程最短),使成本最小化,配送订单最大化,满载率最大化(如由一个配送中心向各个销售点配送货物,通过算法确定配送中心每辆车的配送方案,包括配送至哪个客户,配送量,下一个配送目的地)。 |
【测试数据和说明】 |
|
某物流中心有5台配送车辆,车辆的最大载重均为8T,一次配送的最大行驶距离都为50KM,需要向20个客户送货,物流中心和20个客户的坐标及其客户的需求量随机产生,其中,物流中心的坐标为(14.2KM,13.1km),要求合理安排车辆的配送路线和载重量,使配送总里程最短。 |
客户点 | 横坐标x(km) | 纵坐标y(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.传统贪心算法
#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <cmath>
using namespace std;
double map[21][3] = {14.2,13.1,0,12.8,8.5,0.1,18.4,3.4,0.4,15.4,16.6,1.2,18.9,15.2,1.5,15.5,11.6,0.8,3.9,10.6,1.3,10.6,7.6,1.7,8.6,8.4,1.6,12.5,2.1,1.2,13.8,5.2,0.4,6.7,16.9,0.9,14.8,2.6,1.3,1.8,8.7,1.3,17.1,11,1.9,7.4,1,1.7,0.2,2.8,1.1,11.9,19.8,1.5,13.2,15.1,1.6,6.4,5.6,1.7,9.6,14.8,1.5};
// Is visited?
bool flag[21] = {false};
double Dist(double x1, double y1, double x2, double y2) {
return (double)pow((pow((x2 - x1), 2) + pow((y2 - y1), 2)), 0.5);
}
// Dist Matrix
void Graph(double distances[21][21]) {
for (int i = 0; i < 21; i++) {
for (int j = i + 1; j < 21; j++) {
distances[i][j] = Dist(map[i][0], map[i][1], map[j][0], map[j][1]);
distances[j][i] = distances[i][j];
}
distances[i][i] = 10000;
}
}
// Index of Min Every Row
int SeletMin(double distances[21][21], int row, double sum) {
double min = 10000;
int minIndex = 22;
for (int i = 0; i < 21; i++) {
if (!flag[i] && distances[row][i] < min)
{
min = distances[row][i];
minIndex = i;
}
}
if (minIndex == 22) {
return -1;
}
return minIndex;
}
int main(void) {
double distances[21][21] = {{0}, {0}};
Graph(distances);
double sum_all;
flag[0] = true;
for (int i = 0;i< 5;++i)
{
double sum = 0;
double weight = 0;
int minIndex = 0,finish = 0;
while ((sum + distances[0][finish]) <= 50 || finish== 0)
{
minIndex = SeletMin(distances, minIndex,sum);
if (minIndex == -1)
{
break;
}
if (sum + distances[finish][minIndex] + distances[0][minIndex]>50)
{
break;
}
if (weight + map[minIndex][2]>8)
break;
weight += map[minIndex][2];
cout << minIndex <<' ';
flag[minIndex] = true;
sum += distances[finish][minIndex];
finish = minIndex;
}
if(sum != 0)
{
sum = sum + distances[0][finish];
cout << endl;
cout << sum<< endl;
cout << weight << endl;
}
sum_all += sum;
}
cout << sum_all;
return 0;
}
2.变种贪心算法
每次将最近距离的客户点分配给车。
#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <cmath>
using namespace std;
double map[21][3] = {14.2,13.1,0,12.8,8.5,0.1,18.4,3.4,0.4,15.4,16.6,1.2,18.9,15.2,1.5,15.5,11.6,0.8,3.9,10.6,1.3,10.6,7.6,1.7,8.6,8.4,1.6,12.5,2.1,1.2,13.8,5.2,0.4,6.7,16.9,0.9,14.8,2.6,1.3,1.8,8.7,1.3,17.1,11,1.9,7.4,1,1.7,0.2,2.8,1.1,11.9,19.8,1.5,13.2,15.1,1.6,6.4,5.6,1.7,9.6,14.8,1.5};
// Is visited?
bool flag[21] = {false};
double Dist(double x1, double y1, double x2, double y2) {
return (double)pow((pow((x2 - x1), 2) + pow((y2 - y1), 2)), 0.5);
}
// Dist Matrix
void Graph(double distances[21][21]) {
for (int i = 0; i < 21; i++) {
for (int j = i + 1; j < 21; j++) {
distances[i][j] = Dist(map[i][0], map[i][1], map[j][0], map[j][1]);
distances[j][i] = distances[i][j];
}
distances[i][i] = 10000;
}
}
// Index of Min Every Row
int SeletMin(double distances[21][21], int row, double sum) {
double min = 10000;
int minIndex = 22;
for (int i = 0; i < 21; i++) {
if (!flag[i] && distances[row][i] < min) {
min = distances[row][i];
minIndex = i;
}
}
if (minIndex == 22) {
return -1;
}
return minIndex;
}
int main(void) {
double distances[21][21] = {{0}, {0}};
Graph(distances);
double sum_all = 0;
flag[0] = true;
double sum[5] = {0};
double weight[5] = {0};
int minIndex[5] = {0};
int finish[5] = {0};
int route[5][20] = {{0}, {0}};
int count = 20;
while (count > 0) {
//every vihicle one step
for (int i = 0; i < 5; i++) {
if ((sum[i] + distances[0][finish[i]]) <= 50 || finish[i] == 0) {
minIndex[i] = SeletMin(distances, minIndex[i], sum[i]);
}
if (minIndex[i] == -1) {
break;
}
if (sum[i] + distances[finish[i]][minIndex[i]] + distances[0][minIndex[i]]>50) {
break;
}
if (weight[i] + map[minIndex[i]][2] > 8) {
break;
}
flag[minIndex[i]] = true;
count--;
cout << "第" << i << "辆车选择" << minIndex[i] << endl;
weight[i] += map[minIndex[i]][2];
sum[i] += distances[finish[i]][minIndex[i]];
finish[i] = minIndex[i];
}
}
for (int i = 0; i < 5; i++) {
sum[i] += distances[0][finish[i]];
cout << "第" << i << "辆车路径为" << sum[i] << endl;
sum_all += sum[i];
cout << "第" << i << "辆车重量为" << weight[i] << endl;
}
cout << sum_all << endl;
// for(int i=0;i<21;i++)
// {
// for(int j=0;j<21;j++)
// {
// cout <<"["<< i << "][" << j << "]" << distances[i][j] <<" ";
// }
// cout<<endl;
// }
//while ((sum[i] + distances[0][finish[i]]) <= 50 || finish[i] == 0) {
// minIndex[i] = SeletMin(distances, minIndex[i], sum[i]);
// if (minIndex[i] == -1) {
// break;
// }
// if (sum[i] + distances[finish[i]][minIndex[i]] + distances[0][minIndex[i]]>50) {
// break;
// }
// if (weight[i] + map[minIndex[i]][2] > 8) {
// break;
// }
// weight[i] += map[minIndex[i]][2];
// cout << minIndex[i] <<' ';
// flag[minIndex[i]] = true;
// sum[i] += distances[finish[i]][minIndex[i]];
// finish[i] = minIndex[i];
//}
//if(sum[i] != 0) {
// sum[i] = sum[i] + distances[0][finish[i]];
// cout << endl;
// cout << sum[i] << endl;
// cout << weight[i] << endl;
//}
//sum_all += sum[i];
return 0;
}