TSP问题之状压dp法
首先,我们先来认识一下什么叫做TSP问题
旅行商问题,即TSP问题(Traveling Salesman Problem)又译为旅行推销员问题、货郎担问题,是数学领域中著名问题之一。假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。假设这个n很小,我们就可以使用状态压缩的方法求解,在一般的TSP问题中的用状压求解的题目,我们可以定义一个dp数组,dp[i][v],其中v表示一个集合,dp[i][v]表示到i这个点经过v中所有点的最小路径.
假设我们从s出发,最后再回到s
1.那么最开始,只有dp[s][{s}]=0,其余均等于inf
2.其他情况下,dp[i][state]=min(dp[i][state],dp[j][state']+c[j][i])
3.最后我们的结果,ans=min(ans,dp[i][state]+c[i][s]),因为我们要求的是一个环的最短路,所以还要加上回来的距离
那么还有一个问题,我们要如何存下这个集合,当然是用状态压缩的方法,s|1<<(k),表示由原来的状态s转移到加上k这个点的状态,那么就很好求解了对吧
题目大意:多组数据,给定n,一个起点0,以及这n+1个点之间的距离,求从起点出发经过每个点一次,再回到起点的最短距离.注意到n<=10,我们可以使用状压dp来做
思路:首先先预处理出这n+1个点之间的最短距离,因为n很小,我们可以使用floyed来处理.然后就是套我上面的说的三种情况,具体可以代码中的注解
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#define in(i) (i=read())
using namespace std;
const int inf=0x3f3f3f;
int read()
{
int ans=,f=;
char i=getchar();
while(i<''||i>''){if(i=='-') f=-; i=getchar();}
while(i>=''&&i<='') {ans=(ans<<)+(ans<<)+i-'';i=getchar();}
return ans*f;
}
int n;
int dp[][<<];
int mp[][];
void floyed()
{
for(int k=;k<=n;k++)
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
return;
}
int main()
{
while() {
int ans=inf; in(n);
if(!n) break;
n++;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
in(mp[i][j]);//输入每两个点之间的距离
floyed();//求出n+1个点两两之间的最短距离
memset(dp,inf,sizeof(dp));
dp[][]=;//默认以1为起点,集合内最开始状态为1<<(1-1)=1,所以dp[1][1]=0
for(int i=;i<(<<n);i++)//枚举状态
for(int j=;j<=n;j++)//枚举每个点
if((i&(<<(j-)))!=)//判断这个是否在集合中
for(int k=;k<=n;k++)//如果不在就以它为中转点转移
if(!(i&(<<(k-))))
dp[k][i|(<<(k-))]=min(dp[k][i|(<<(k-))],dp[j][i]+mp[j][k]);//状态转移方程
for(int i=;i<=n;i++)
ans=min(ans,dp[i][(<<n)-]+mp[i][]);//还要回来才是一个环,因此还要加上到起点的距离
cout<<ans<<endl;
}
}
上述代码在洛谷应该是会T一个点的,因为重复使用位运算速度是会变慢的,所以我们可以提前处理出每个点左移多少位之后的数组,以及使用系统自带函数min也是很慢的\
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#define MIN(a,b) (a)<(b)?(a):(b)
#define in(i) (i=read())
using namespace std;
const int inf=0x3f3f3f;
int read()
{
int ans=,f=;
char i=getchar();
while(i<''||i>'') {if(i=='-') f=-; i=getchar();}
while(i>=''&&i<='') { ans=(ans<<)+(ans<<)+i-'';i=getchar();}
return ans*f;
}
int dp[<<][],mp[][],st[];
int n;
int main()
{
in(n);
int ans=inf;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
in(mp[i][j]);
memset(dp,inf,sizeof(dp));
dp[][]=; st[]=;
for(int i=;i<=;i++) st[i]=st[i-]<<;//预处理
for(int i=;i<st[n];i++)
for(int j=;j<=n;j++)
if( dp[i][j]!=dp[][] && i&st[j-])
for(int k=;k<=n;k++)
if(!(i&st[k-]))
dp[i|st[k-]][k]=MIN(dp[i|st[k-]][k],dp[i][j]+mp[j][k]);
for(int i=;i<=n;i++)
ans=MIN(ans,dp[st[n]-][i]+mp[i][]);
printf("%d\n",ans);
return ;
}
TSP问题之状压dp法的更多相关文章
- HDU 5418 Victor and World (可重复走的TSP问题,状压dp)
题意: 每个点都可以走多次的TSP问题:有n个点(n<=16),从点1出发,经过其他所有点至少1次,并回到原点1,使得路程最短. 思路: 给了很多重边,选最小的留下即可.任意点可能无法直接到达, ...
- POJ 3311 Hie with the Pie (状压DP)
题意: 每个点都可以走多次的TSP问题:有n个点(n<=11),从点1出发,经过其他所有点至少1次,并回到原点1,使得路程最短是多少? 思路: 同HDU 5418 VICTOR AND WORL ...
- poj3311 TSP经典状压dp(Traveling Saleman Problem)
题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...
- HDU 5067 Harry And Dig Machine(状压DP)(TSP问题)
题目地址:pid=5067">HDU 5067 经典的TSP旅行商问题模型. 状压DP. 先分别预处理出来每两个石子堆的距离.然后将题目转化成10个城市每一个城市至少经过一次的最短时间 ...
- POJ3311 Hie with the Pie 【状压dp/TSP问题】
题目链接:http://poj.org/problem?id=3311 Hie with the Pie Time Limit: 2000MS Memory Limit: 65536K Total ...
- 状压DP 从TSP问题开始入门哦
一开始学状压DP难以理解,后来从TSP开始,终于入门了nice!!!! 旅行商问题 : 给定n个城市和两两相互的距离 ,求一条路径经过所有城市,并且路径达到最下仅限于; 朴树想法: 做n个城 ...
- Hie with the Pie(POJ3311+floyd+状压dp+TSP问题dp解法)
题目链接:http://poj.org/problem?id=3311 题目: 题意:n个城市,每两个城市间都存在距离,问你恰好经过所有城市一遍,最后回到起点(0)的最短距离. 思路:我们首先用flo ...
- DAG求最短路--TSP变形--状压dp
DAG状压dp的一种 题目: $m$个城市,$n$张车票,第i张车票上的时间是$t_i$, 求从$a$到$b$的最短时间,如果无法到达则输出“impossible” 解法: 考虑状态:“现在在城市$v ...
- 状压DP小结
看了一个多星期状压DP,总算有点明白,大概可以分为两种:数据是在矩阵中的,数据是线性的,在矩阵中的一般就是排兵布阵这一种的,还有一种线性结构中给定条件让你求最大权值,比如求最大权值路线,TSP问题等, ...
随机推荐
- python3 练习题100例 (二十三)与7相关的数
与7相关的数:如果一个正整数,它能被7整除或者它的十进制表示法中某个位数上的数字为7,则称之为与7相关的数.(10分) 题目内容: 现在我们给定一个正整数n(n<1000),求所有小于等于n的与 ...
- PHP json_decode返回null解析失败原因
在PHP5.4之前 json_decode函数有两个参数json_decode有两个参数,第一个是待解析的字符串,第二个是是否解析为Array json_decode要求的字符串比较严格:(1)使用U ...
- C语言结构体的学习,以及gdb的调式
#include <stdio.h> #include <string.h> #define format "%d\n%s\n%f\n%f\n%f\n" t ...
- (数据科学学习手札35)tensorflow初体验
一.简介 TensorFlow时谷歌于2015年11月宣布在Github上开源的第二代分布式机器学习系统,目前仍处于快速开发迭代中,有大量的新功能新特性在陆续研发中: TensorFlow既是一个实现 ...
- POJ1236_A - Network of Schools _强连通分量::Tarjan算法
Time Limit: 1000MS Memory Limit: 10000K Description A number of schools are connected to a compute ...
- poj 2393 奶牛场生产成本问题 贪心算法
题意:有一个奶牛场,第i周的生产成本为c,需要数量为 y,每周的存储成本为s.问怎么安排使得成本最低? 思路: 成本最低是吧?求出每周的最低成本*该周需要的数量就是成本最低 每周的成本有两个:自己本周 ...
- TreeMap与LinkedHashMap的区别
TreeMap是根据元素的内部比较器进行排序的,它可以根据key值的大小排序: LinkedHashMap是保持存放顺序的. TreeMap采用红黑树算法,遍历效率高: LinkedHashMap采用 ...
- Code First Migrations更新数据库结构(数据迁移) 【转】
注意:一旦正常后,每次数据库有变化,做如下两步: 1. Enable-Migrations 2.update-database 背景 code first起初当修改model后,要持久化至数据库中时, ...
- 实现一个简单版的express
express应该算是早期最优秀的一个node框架了,刚开始学node做后端语言就是用的express,它的cli可以帮我们搭建好项目目录,就像现在的vue,react一样.express本身没有做太 ...
- 使用polarssl进行RSA加密解密
RSA算法的原理就不提了,网上有很多介绍的文章,因为项目中使用RSA加密,所以需要找一个RSA加密的算法,之前尝试过使用Crypto++库,无奈Crypto++其中使用了大量的模版,各种继承,看着头大 ...