VRP--车辆路径问题 c++

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

【测试数据和说明】
某物流中心有5台配送车辆,车辆的最大载重均为8T,一次配送的最大行驶距离都为50KM,需要向20个客户送货,物流中心和20个客户的坐标及其客户的需求量随机产生,其中,物流中心的坐标为(14.2KM,13.1km),要求合理安排车辆的配送路线和载重量,使配送总里程最短。
客户点横坐标x(km)纵坐标y(km)需求量q(t)
112.88.50.1
218.43.40.4
315.416.61.2
418.915.21.5
515.511.60.8
63.910.61.3
710.67.61.7
88.68.40.6
912.52.11.2
1013.85.20.4
116.716.90.9
1214.82.61.3
131.88.71.3
1417.1111.9
157.411.7
160.22.81.1
1711.919.81.5
1813.215.11.6
196.45.61.7
209.614.81.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;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萌新待开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值