TSP_旅行商问题 - 蛮力法DFS

一、前言

    【旅行商问题】旅行商问题(TravelingSalesmanProblem,TSP)是一个经典的组合优化问题。经典的TSP可以描述为:一个商品推销员要去若干个城市推销商品,该推销员从一个城市出发,需要经过所有城市后,回到出发地。应如何选择行进路线,以使总的行程最短。从图论的角度来看,该问题实质是在一个带权完全无向图中,找一个权值最小的Hamilton回路。由于该问题的可行解是所有顶点的全排列,随着顶点数的增加,会产生组合爆炸,它是一个NP完全问题。由于其在交通运输、电路板线路设计以及物流配送等领域内有着广泛的应用,国内外学者对其进行了大量的研究。早期的研究者使用精确算法求解该问题,常用的方法包括:分枝定界法、线性规划法、动态规划法等。但是,随着问题规模的增大,精确算法将变得无能为力,因此,在后来的研究中,国内外学者重点使用近似算法或启发式算法,主要有遗传算法模拟退火法蚁群算法禁忌搜索算法、贪婪算法神经网络等。【参考百度百科】。

二、本文概要

    本文基于蛮力法(此处采用深度优先遍历,DFS)解决旅行商问题。通过遍历出所有满足条件的路径情况,并保持更新最优解,直到所有情况都遍历完,得到全局最优解。但是,使用蛮力法需要遍历的城市个数高达city_num的阶乘,当city_num=12的时候,需遍历479001600种情况,程序所需时间以小时为单位。

运行结果

代码:

#include <iostream>
#include <cstring>

using namespace std;
const int maxSize = 999;
int arcNum,vertexNum,pathNum,pathIndex = 1,bestLength = maxSize;//pathIndex表示当前已经经过的点数
int vertex[maxSize],visited[maxSize];
int arc[maxSize][maxSize];
int path_DFS[maxSize][maxSize];//存放走过的路径
int length_DFS[maxSize];//存放每条路径对应的长度

void DFS(int index)
{
    if(pathIndex == vertexNum&&arc[index][1] != 0)
    {
        path_DFS[pathNum][pathIndex] = index;//当前到达的点
        path_DFS[pathNum][pathIndex + 1] = 1; // 最后一个到达的位置为1号点
        length_DFS[pathNum] = 0; // 存储最短路径
        //计算最短的路径
        for(int i = 1;i <= vertexNum;i++)
        {
            //当前点到下一个点的距离
            length_DFS[pathNum] += arc[path_DFS[pathNum][i]][path_DFS[pathNum][i + 1]];
        }
        if(bestLength > length_DFS[pathNum])
        {
            bestLength = length_DFS[pathNum];
        }
        for(int i = 1;i <= vertexNum + 1;i++)
        {
            cout << path_DFS[pathNum][i] << " ";
            path_DFS[pathNum + 1][i] = path_DFS[pathNum][i];
        }
        cout << endl << "length"<< length_DFS[pathNum] <<endl;
        pathNum++;
        return;
    }
    else
    {
        for(int i = 1;i <= vertexNum;i++)
        {
            if(arc[index][i] > 0&&visited[i] == 0)
            {
                visited[i] = 1;
                path_DFS[pathNum][pathIndex] = index;
                pathIndex++;
                DFS(i);
                visited[i] = 0;
                pathIndex--;
            }
        }
    }
}

int main()
{
    memset(visited,0,sizeof(visited));
    cin >> arcNum >> vertexNum;
    for(int i = 1;i <= vertexNum;i++)
    {
        vertex[i] = i;
    }
    for(int k = 0;k < arcNum;k++)
    {
        int i,j,weight;
        cin >> i >> j >> weight;
        arc[i][j] = weight;
        arc[j][i] = weight;
    }
    //一号点已经走过了
    visited[1] = 1;
    DFS(1);
    cout << bestLength << endl;
    return 0;
}

 

  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值