优先队列式分支限界法解决旅行售货商问题

优先队列式分支限界法解决旅行售货商问题

问题描述:
某售货员要到若干城市去推销商品,已知各城市之间的路程(或旅费)。
他要选定一条从驻地出发,经过每个城市一次,最后回到驻地的路线,使总的路程(或总旅费)最小。 

路线是一个带权图,图中各边的费用(权)为正数。
图的一条周游路线是包括V中的每个顶点在内的一条回路。
周游路线的费用是这条路线上所有边的费用之和。 

在这里插入图片描述

带权图邻接矩阵为:
 0  30   6   4
30   0   5  10
 6   5   0  20
 4  10  20   0
#include <bits/stdc++.h>

using namespace std;

//优先队列式分支限界法解决旅行售货商问题

struct node
{
    int lcost;     //费用下界
    int cc;        //当前费用
    int rcost;     //当前及剩余顶点最小出边费用和
    int s;          //当前节点在排列树中的层次
    int x[5];         //节点路径
    bool operator <(const node &a) const
    {
        return lcost > a.lcost;
    }

};

void print(node& no, int n)
{
    cout << "最优解:" << endl;
    for(int i = 1; i <= n; ++i)
    {
        cout << no.x[i] << " ";
    }
    cout << endl;
    cout << "最优值: " << no.lcost << endl;
}

int main()
{
    //城市数
    int n = 4;

    int a[5][5] = {{}, {0, 0, 30, 6, 4}, {0, 30, 0, 5, 10}, {0, 6, 5, 0, 20}, {0, 4, 10, 20, 0}};
    int rcostSelf[5] = {};
    cout << "邻接矩阵为:" << endl;
    for(int i = 1; i <= 4; ++i)
    {
        int min = a[i][1];
        for(int j = 1; j <= 4; ++j)
        {
            cout << setw(2) << a[i][j] << "  ";
            if((a[i][j] < min || min == 0)&& a[i][j] != 0)
            {
                min = a[i][j];
            }
        }
        rcostSelf[i] = min;
        cout << endl;
    }




    cout << "\n最小出度数组:" << endl;
    for(int i = 1; i <= n; ++i)
    {
        cout << rcostSelf[i] << " ";
    }
    cout << "\n\n";





    priority_queue<node> priQueue;

    {
        //从1号城市出发,初始化起始节点
        node firstNode;
        firstNode.rcost = 0;

        for(int i = 1; i <= n; ++i)
        {
            firstNode.rcost += rcostSelf[i];
        }


        firstNode.lcost = firstNode.rcost;
        firstNode.cc = 0;
        firstNode.s = 1;
        for(int i = 1; i <= n; ++i)
        {
            firstNode.x[i] = i;
        }
        priQueue.push(firstNode);
        int bestc = INT_MAX;
        while(true)
        {
            node tmpTop = priQueue.top();
            priQueue.pop();


            cout << "====================\n当前活结点信息:" << endl;
            cout << "层数:" << tmpTop.s << endl;
            cout << "当前局部解:" << endl;
            for(int i = 1; i <= tmpTop.s; ++i)
            {
                cout << tmpTop.x[i] << "  ";
            }
            cout << endl;
            cout << "rcost = " << tmpTop.rcost << endl;
            cout << "cc = " << tmpTop.cc << endl;
            cout << "lcost = " << tmpTop.lcost << endl;
            cout << "====================\n" << endl;


            int num = n - tmpTop.s;
            if(tmpTop.s == 4)
            {
                print(tmpTop, n);
                break;
            }
            for(int i = 1; i <= num; ++i)
            {
                node* tmp = new node;
                tmp->s = tmpTop.s + 1;
                for(int j = 1; j <= n; ++j)
                {
                    tmp->x[j] = tmpTop.x[j];
                }

                tmp->cc = tmpTop.cc + a[tmp->x[tmpTop.s]][tmp->x[tmpTop.s + i]];
                int t = tmp->x[tmpTop.s + i];
                tmp->x[tmpTop.s + i] = tmp->x[tmpTop.s + 1];
                tmp->x[tmpTop.s + 1] = t;
                tmp->rcost = 0;
                for(int j = tmpTop.s + 1; j <= n; ++j)
                {
                    tmp->rcost += rcostSelf[tmp->x[j]];
                }
                if(tmp->s == n-1)
                {
                    int bestx = tmp->cc + a[ tmp->x[n-1] ][ tmp->x[n] ] + a[ tmp->x[1] ][ tmp->x[n] ];
                    if(bestx < bestc)
                    {
                        bestc = bestx;
                    }
                    tmp->lcost = bestx;
                }
                else if(tmp->s == n)
                {
                    tmp->lcost = tmpTop.lcost;
                }
                else
                    tmp->lcost = tmp->rcost + tmp->cc;
                if(tmp->lcost > bestc)
                {
                    cout << "减去" << endl;
                    continue;
                }
                priQueue.push(*tmp);
            }

        }
    }

    return 0;
}
最终结果:
最优解:	x = {1, 4, 2, 3}
最优值:	25
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值