旅行商问题【状压dp】

本文介绍了旅行商问题(TSP),一个经典的数学难题。通过动态规划的方法,详细阐述了如何解决规模较小的TSP问题,特别是使用状压dp的思路。文章详细解释了动态规划的状态转移方程,并给出了实现代码,包括初始状态设置、状态枚举和转移过程。最后,讨论了当去除每个城市只能拜访一次的限制时,如何利用Floyd算法求解。
摘要由CSDN通过智能技术生成

一。问题介绍

旅行商问题,即TSP问题(Travelling Salesman Problem)又译为旅行推销员问题、货郎担问题,是数学领域中著名问题之一。假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求的路径路程为所有路径之中的最小值。

二。解决方法(理论)

TSP是一道经典的NP-完全问题。在规模比较小的时候,可以用动态规划求解。

有n个城市,两两之间均有道路直接相连,给出每个城市i和j之间的道路长度dist(i, j)。求一条经过每个城市一次且仅一次,最后回到起点的路线,使得经过的道路总长度最短。n<=16,城市编号为0~n-1。

因为路线是一个环,可以规定任意点为起点和终点,不妨设城市0为起点和终点。设d(s,i)表示“当前在i城市,已访问城市集合为s”的最短长度,则d(s, i)=min{d(s - i, j) + dist(j, i) | i∈S}.

初始时d({0},0)=0,最终答案为min{d({0,1,2,,,,n-1}, i) + dist(i, 0) | i≠0}

时间复杂度为O(n^{2}2^{^{n}})。

根据该思路可以写下如下代码:

memset(dp, 0x3f, sizeof(dp));
dp[1][0] = 0;
for (int s = 0; s < (1<<n); s++) {    //枚举集合状态s
    for (int i = 0; i < n; i++) {     //枚举当前的点i
        if (s & (1<<i)) {
            for (int j = 0; j < n; j++) {    //枚举之前的点j
                if (j != i && (s & (1<<j)) {
                    dp[s][i] = min(dp[s][i], dp[s ^ (1<<i)][j] + dist[j][i]);    //根据之前的点j,更新当前的点i。
                }
            }
        }
    }
}
int ans = INF:
for (int i = 1; i < n; i++) {    //注意这里的i是从1开始的,因为访问城市的时候我们规定从0号城市访问,要走一个回路需要走n步,第n-1步必须是非0号城
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值