首先,我们先来认识一下什么叫做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这个点的状态,那么就很好求解了对吧

POJ3311

题目大意:多组数据,给定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法的更多相关文章

  1. HDU 5418 Victor and World (可重复走的TSP问题,状压dp)

    题意: 每个点都可以走多次的TSP问题:有n个点(n<=16),从点1出发,经过其他所有点至少1次,并回到原点1,使得路程最短. 思路: 给了很多重边,选最小的留下即可.任意点可能无法直接到达, ...

  2. POJ 3311 Hie with the Pie (状压DP)

    题意: 每个点都可以走多次的TSP问题:有n个点(n<=11),从点1出发,经过其他所有点至少1次,并回到原点1,使得路程最短是多少? 思路: 同HDU 5418 VICTOR AND WORL ...

  3. poj3311 TSP经典状压dp(Traveling Saleman Problem)

    题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...

  4. HDU 5067 Harry And Dig Machine(状压DP)(TSP问题)

    题目地址:pid=5067">HDU 5067 经典的TSP旅行商问题模型. 状压DP. 先分别预处理出来每两个石子堆的距离.然后将题目转化成10个城市每一个城市至少经过一次的最短时间 ...

  5. POJ3311 Hie with the Pie 【状压dp/TSP问题】

    题目链接:http://poj.org/problem?id=3311 Hie with the Pie Time Limit: 2000MS   Memory Limit: 65536K Total ...

  6. 状压DP 从TSP问题开始入门哦

      一开始学状压DP难以理解,后来从TSP开始,终于入门了nice!!!! 旅行商问题 :    给定n个城市和两两相互的距离 ,求一条路径经过所有城市,并且路径达到最下仅限于; 朴树想法: 做n个城 ...

  7. Hie with the Pie(POJ3311+floyd+状压dp+TSP问题dp解法)

    题目链接:http://poj.org/problem?id=3311 题目: 题意:n个城市,每两个城市间都存在距离,问你恰好经过所有城市一遍,最后回到起点(0)的最短距离. 思路:我们首先用flo ...

  8. DAG求最短路--TSP变形--状压dp

    DAG状压dp的一种 题目: $m$个城市,$n$张车票,第i张车票上的时间是$t_i$, 求从$a$到$b$的最短时间,如果无法到达则输出“impossible” 解法: 考虑状态:“现在在城市$v ...

  9. 状压DP小结

    看了一个多星期状压DP,总算有点明白,大概可以分为两种:数据是在矩阵中的,数据是线性的,在矩阵中的一般就是排兵布阵这一种的,还有一种线性结构中给定条件让你求最大权值,比如求最大权值路线,TSP问题等, ...

随机推荐

  1. Python基本数据类型(一)

    我会持续更新.... 字符串类型 字符串定义: 字符串的格式:'字符串', "字符串", """字符串"""字符串一旦被 ...

  2. ruby 数据类型Number

    Ruby支持的数据类型包括基本的Number.String.Ranges.Symbols,以及true.false和nil这几个特殊值,同时还有两种重要的数据结构——Array和Hash 数值类型(N ...

  3. 使用postgresql作为cm的数据库时候添加报错

    如下图,当postgresql安装成功,建立好数据库scm,rman,amon之后,添加cm对应服务报错hadoopNode2没有相应数据库: No database server found run ...

  4. CCS实例,网页栏目

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  5. C#导出数据到CSV和EXCEL文件时数字文本被转义的解决方法

    今天写C#导出datagrid数据到csv格式文件的时候,发现不管怎么尝试,凡是单元格里面全是数字的单元格,在用Excel打开的时候,都被自动转义成数据格式.数据查看极其不方便.最后google了一下 ...

  6. sqlserver一次性删除master数据库中的所有用户添加的表

    use master; go sp_msforeachtable @command1="drop table ?" go

  7. javascript的优美与鸡肋

    --总结来自:<javascript语言精粹> 任何语言都有其优美的地方和其鸡肋的地方.避归一些语言的糟粕,能相应的降低bug出现的几率. 优美处: 函数是头等对象 基于原型继承的动态对象 ...

  8. 【APUE】Chapter10 Signals

    Signal主要分两大部分: A. 什么是Signal,有哪些Signal,都是干什么使的. B. 列举了非常多不正确(不可靠)的处理Signal的方式,以及怎么样设计来避免这些错误出现. 10.2 ...

  9. 30分钟快速搭建Web CRUD的管理平台--django神奇魔法

    加上你的准备的时间,估计30分钟完全够用了,因为最近在做爬虫管理平台,想着快速开发,没想到python web平台下有这么非常方便的框架,简洁而优雅.将自己的一些坑总结出来,方便给大家的使用. 准备环 ...

  10. 「题目代码」P1029~P1033(Java)

    1029 C基础-求解方程 import java.util.*; import java.io.*; import java.math.BigInteger; public class Main { ...