分支限界法的旅行商问题

分支限界法的旅行商问题(TSP)

旅行推销员问题( 英语:Travelling salesman problem, TSP)是这样一个问题:给定一系列城市和每对城市之间的距离,求解访问每一座城市一次并回到起始城市的最短回路。它是组合优化中的一个NP困难问题,在运筹学和理论计算机科学中非常重要。
分支限界法在上一篇Blog中我有简单说明,并给出了基于分支界限法的Dijkstra ,这篇文章里介绍一下基于分支限界法的TSP算法。

对于TSP,我们需要利用上界和下界来对BFS进行剪枝,通过不断更新上界和下界,尽可能的排除不符合需求的child,以实现剪枝。最终,当上限和下限等同时,我们可以获得最优的BFS解,以解决TSP问题。

在第一篇中,我们用dfs获取上界,用每行矩阵最小值来获取下界。

代码如下,下面代码中,我采用贪心法(使用DFS暴力搜索到一个结果)来获取最初的上界,通过累加每行旅行商矩阵中的最小值来获取一个下界。

// MinTraveling.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include<queue>

using namespace std;



template<class Type>
class MinHeapNode
{
    template<class Type>
    friend class Traveing;
public:
    operator Type ()const { return lcost; }
private:
    Type lcost,//下限
        cc,
        rcost;//当前的费用
    int s,
        * x;
};

template<class Type>
class Traveing
{
    friend int main(void);
public:
    Type BBTSP(int v[]);
private:
    int n;
    Type** a,
        cc,
        bestc,
        NoEdge;
};

 template<class Type>
 Type Traveing<Type>::BBTSP(int v[])
 {
     priority_queue<MinHeapNode<Type>, vector<MinHeapNode<Type>>, greater<MinHeapNode<Type>>> priority;
    
     Type MinSum = 0;
     Type* MinOut = new Type[n + 1];
     for (int i = 0; i < 4; i++)
     {
         Type Min = NoEdge;
         for (int j = 0; j < 4; j++)
             if (a[i][j] != NoEdge && (a[i][j] < Min || Min == NoEdge))
                 Min = a[i][j];
         MinOut[i] = Min;
         MinSum += Min;
     }
     MinHeapNode<Type> E;
     E.x = new Type[n + 1];
     for (int i = 0; i < 5; i++)
         E.x[i] = i;
     E.s = 0;
     E.rcost = MinSum;
     E.cc = 0;
     Type bestc = NoEdge;
     while (E.s<n-1)
     {
         if (E.s == n - 2)
         {
             if (a[E.x[E.s]][E.x[E.s + 1]] != NoEdge && a[E.x[E.s + 1]][0] != NoEdge &&
                 (bestc == NoEdge || E.cc + a[E.x[E.s]][E.x[E.s + 1]] + a[E.x[E.s + 1]][0] < bestc))
             {
                 bestc = E.cc + a[E.x[E.s]][E.x[E.s + 1]] + a[E.x[E.s + 1]][0];
                 E.cc = bestc;
                 //E.x[E.s+1] = E.x[E.s + 1];
                 E.s++;
                 E.lcost = bestc;
                 priority.push(E);
             }
             else
             {
                 delete[] E.x;
             }
         }
         else
         {
             for (int i = E.s + 1; i < n; i++)
             {
                 if (a[E.s][i] != NoEdge)
                 {
                     Type cc = E.cc + a[E.s][i];
                     Type rcost = E.rcost - MinOut[E.x[E.s]];
                     Type b = cc + rcost;
                     if (b < bestc || bestc == NoEdge)
                     {
                         MinHeapNode<Type> N;
                         N.cc = cc;
                         N.lcost = b;
                         N.rcost = rcost;
                         N.s = E.s + 1;
                         N.x = new Type[n + 1];
                         for (int i = 0; i <= n; i++)
                             N.x[i] = E.x[i];
                         //Type temp = N.x[E.s + 1];
                         N.x[E.s + 1] = E.x[i];
                         N.x[i] = E.x[E.s + 1];
                         priority.push(N);
                     }
                 }
             }
             delete[] E.x;
         }
         if (priority.empty())
             break;
         E = priority.top();
         priority.pop();
     }
     if (bestc == NoEdge)
         return NoEdge;
     for (int i = 0; i < 5; i++)
         v[i] = E.x[i];
     while (true)
     {
         delete[] E.x;
         if (priority.empty())
             break;
         E = priority.top(); 
         priority.pop();
     }
     return bestc;
 }

int main()
{
    int** A;
    A = new int* [4];
    for (int i = 0; i < 4; i++)
        A[i] = new int[4];
    
    A[0][0] = -1, A[0][1] = 30, A[0][2] = 6, A[0][3] = 4;
    A[1][0] = 30, A[1][1] = -1, A[1][2] = 5, A[1][3] = 10;
    A[2][0] = 6, A[2][1] = 5, A[2][2] = -1, A[2][3] = 20;
    A[3][0] = 4, A[3][1] = 10, A[3][2] = 20, A[3][3] = -1;
    int v[5];
    Traveing<int> traveing;
    traveing.a = A;
    traveing.n = 4;
    traveing.NoEdge = -1;
    cout << traveing.BBTSP(v) << endl;

    for (int i = 0; i < 4; i++)
        cout << v[i] << "\t";
    cout << endl;

    return 0;
}
  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值