旅行商问题(状态压缩dp)

给定一个n个顶点的带权有向图的距离矩阵d(i,j)(INF表示没有边)。要求从顶点0出发,经过每个顶点恰好一次再回到顶点0,求所经过边的总权重的最小值。

这就是著名的旅行商问题(TSP,Travelling Salemans Problem)。TSP问题是NP困难的,没有已知的多项式时间的高效算法可以解决这一问题(别问我这是什么~~~~(>_<)~~~~)。不过在程序设计中数据比较小的题目还是可能出现的。所有可能的路线总共有(n-1)!种,可以用dp来解决。
 

假设现在已访问过的顶点的集合为S(顶点0当做未访问的顶点),当前所在顶点为v,用dp[S][v]表示从v出发访问剩余的所有顶点,最终回到顶点0的路径的权重总和的最小值。由于从v出发可以移动到任意的一个顶点u(u不属于S),因此有如下递推式:dp[V][0]=0,dp[S][v]=min{dp[S+u][u]+d[v][u]}。用这个递推式就可以计算出所求结果。不过在递推式中有一个下标不是整数而是集合,对于集合我们可以把每个元素的选取与否对应到一个二进制位里,从而把状态压缩成一个整数,大大简化了计算和维护。忘记说了,想学好状压dp,首先要熟练掌握位运算╮(╯_╰)╭。(这是在《挑战程序设计竞赛》里看到的)

直接贴代码了。

#include<iostream>
#include<cstring>
using namespace std;
#define INF 1e9
#define maxn 20
int dp[1<<maxn][maxn];
int n=5;
int d[maxn][maxn]={
        {INF,3,INF,4,INF},
        {INF,INF,5,INF,INF},
        {4,INF,INF,5,INF},
        {INF,INF,INF,INF,3},
        {7,6,INF,INF,INF}
};
int rec(int S,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值