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