TSP:给定n个点,m条无向边,每条边有一个权值代表两个点之间的距离,现在要求把每一个点都走一遍并回到原点,求路径的最短值。

对于现在走到的点i,它前面会有k给点,后面有s个点,那么与最短路有关的就是后面s给点应该如何走,而前面的k个点,我们只需记录走过这几个点所需的最短路。

那么就可以用状压dp,比方说现在走到i点,01串用来代表之前走过的状态,比如n=7,i=2,01串(我们叫它st好了)是0011010,就代表2、4、5点是走过的(走过的点标1,一开始的状态就应该全是0),其中现在处在点2。那么dp[st][i]就应该表示此时在i点,状态为st时走过的最短路。

上图的黄色和绿色线分别对应两种不同的路径,我们会发现,对于每一条路,所有点都是要经过的,那么其实起点选哪个都没有关系,因为在一条路径里所有点的地位应该是相同的,从1出发,会首先把剩余四个点都走完,再从最后一个点回到1;从2或3、4、5出发,思路是相同的,而且他们走过的路径是一样的,所以我说从哪个点开始都没有关系。

既然如此,就不妨从点1开始吧!

既然是dp,那么就应该有递推,我们可以从最后的状态开始讨论(很正常的思路)。

最后的状态是:刚好把所有点都踩了一遍,然后来到了点k(k!=1),如果k与1之间存在边的话,就连在一起,路就走完了,那么这个状态就是合法的,将这条路对应的最短路径加上该点到点1的路径长度,与ans进行比较,进行更新就可以了。

如果k与1之间没有边的话,这个状态就是非法的,排除。

接下来,我们可以用记忆化搜索,先定义一个st=111...1(n个1),代表所有点都踩过的情况,

然后用i从1到n循环,与ans进行对比的就是f[st][i]+mas[i][1],最后输出ans即可。

现在唯一的问题就是如何递推来求f[st][i]。

st当中第i位一定是1,代表第i点走过了,我们要求f[st][i]的话,得先还原出到达i点之前的状态,也就是把第i位变成0,得到st1(原状态)。

然后,对于剩下的st当中为1的点(代表来到第i点之前已经走过的点),如果它们与点i有边连接的话,就可以通过求出dp[st1][j]+mas[j][i](j代表之前走过,现在枚举到的点),并通过横向对比,来求出最小值作为f[st][i]即可。

部分细节放在代码里:(代码末有测试样例,答案应为17(可以自己手搓))

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll f[(1<<20)+10][25];//st状态下停在i点的最短路;
ll mas[23][23];
ll n,m,x,y,z;
ll deal(ll st,ll x)//记忆化搜索
{if(f[st][x]!=0x3f3f3f3f3f3f3f3f) //代表已经被处理过了; return f[st][x];ll st1=st-(1<<(x-1));//来到这一点前的状态,也就是第x个点还没有走过for(int i=1;i<=n;++i){if(mas[i][x]==0) continue;if((st>>(i-1))&1){f[st][x]=min(f[st][x],deal(st1,i)+mas[i][x]);  }} return f[st][x];
}
int main()
{cin>>n>>m;//n个点,m条边 for(int i=1;i<=m;++i){cin>>x>>y>>z;mas[x][y]=z;mas[y][x]=z;//无向边 } memset(f,0x3f,sizeof f);//初始化f[1][1]=0;//初始化,??????????ll st=(1<<n)-1;//n位全部变成1,代表此时n个点都踩完了。 ll ans=1e12;for(int i=2;i<=n;++i){int tmp=deal(st,i);if(mas[i][1]!=0) ans=min(ans,tmp+mas[i][1]); } cout<<ans<<endl;return 0;
}
/*
样例:
5 9
1 2 2
1 3 7
1 4 2
1 5 4
2 3 10
2 4 6
2 5 3
3 4 4
4 5 1
*/

这其实用了很经典的状压思路,将所有状态压缩成01串来表示,通常用于状态数不大的情况。

下面给出一道例题(也是状压的思路)

看这里

大意:
FJ的N(4 <= N <= 16)头奶牛中的每一头都有一个唯一的编号S_i (1 <= S_i <= 25,000). 奶牛为她们的编号感到骄傲, 所以每一头奶牛都把她的编号刻在一个金牌上, 并且把金牌挂在她们宽大的脖子上. 奶牛们对在挤奶的时候被排成一支”混乱”的队伍非常反感. 如果一个队伍里任意两头相邻的奶牛的编号相差超过K (1 <= K <= 3400), 它就被称为是混乱的. 比如说,当N = 6, K = 1时, 1, 3, 5, 2, 6, 4 就是一支”混乱”的队伍, 但是 1, 3, 6, 5, 2, 4 不是(因为5和6只相差1). 那么, 有多少种能够使奶牛排成”混乱”的队伍的方案呢?

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,s;
ll mas[20];
ll dp[20][(1<<18)+10];//状态为j且队尾为i的情况下可行的方案数
int main()
{cin>>n>>s;for(int i=1;i<=n;++i) cin>>mas[i];for(int i=1;i<=n;++i) dp[i][1<<(i-1)]=1; //初始化 for(ll i=0;i<(1<<n);++i){for(int j=1;j<=n;++j){if(i&(1<<(j-1))){for(int k=1;k<=n;++k){if((i&(1<<(k-1)))) continue;if(abs(mas[j]-mas[k])<=s) continue;dp[k][i+(1<<(k-1))]+=dp[j][i];}}}}ll ans=0;for(int i=1;i<=n;++i){ans+=dp[i][(1<<n)-1];   }cout<<ans<<endl;return 0;
}

TSP问题详解(旅行商问题)相关推荐

  1. 蚁群算法--旅行商(TSP)问题详解

    蚁群算法--旅行商(TSP)问题详解 蚁群算法 问题与分析 结果显示与分析 蚁群算法 蚁群算法(ant colony optimization)最早是由Marco Dorigo等人在1991年提出,他 ...

  2. 神经网络算法详解 04:反馈神经网络(Hopfield、BAM、BM、RBM)

    本文介绍了反馈神经网络,包括Hopfield网络,离散Hopfield网络(DHNN),连续Hopfield网络(CHNN),双向联想记忆网络(BAM),玻尔兹曼机(BM),受限玻尔兹曼机(RBM). ...

  3. 遗传算法详解与改良遗传算法

    1.遗传算法简介 遗传算法(GA)是用于解决NP难问题如JSP问题,TSP问题常用的启发式算法.上世纪70年代由美国的John holland提出,是运用计算机仿真,通过交叉变异等方式,模拟自然进化过 ...

  4. (转)dp动态规划分类详解

    dp动态规划分类详解 转自:http://blog.csdn.NET/cc_again/article/details/25866971 动态规划一直是ACM竞赛中的重点,同时又是难点,因为该算法时间 ...

  5. Lenet5实现及代码详解——以MINST数据集为例

    看了卷积神经网络(CNN)的原理及介绍,想着自己动手解决一个案例,在网上也看了很多博客,这里整理一下,顺便记录一下自己解决一个完成的CNN实例的过程,以便以后方便看. 如果有不足之处,欢迎大家指正. ...

  6. WINDOWS系统服务详解

    1 WINDOWS系统服务详解    --  WINDOWS系统服务详解 <P>1 Alerter 当系统发生故障时向管理员发送错误警报,除非电脑处于局域网,而且配有网络管理员,一 般不需 ...

  7. JavaMail详解

    引用自http://blog.sina.com.cn/s/articlelist_1832656582_7_1.html [JavaMail]1 基础 A.简介 JavaMail,顾名思义,提供给开发 ...

  8. 回溯法解旅行商问题java,回溯法解旅行商问题 | 学步园

    第一次编写,格式写的比较混乱.先把源码上来吧.这个源码是模仿教材上的(本人学生一枚 ).分析过程在下面. #include using namespace std; class Traveling{ ...

  9. Miracast技术详解(三):RTP MPEG2-TS

    Miracast音视频流概述 在上一篇文章中,我们已经成功完成RTSP能力协商与会话的建立,并准备开始音视频流的传输阶段.那么下一步,就是对音视频流进行解析,并将音视频展示给用户的过程.这样整个Mir ...

  10. I2C详解(4) I2C总线的规范以及用户手册(3) I2C电气规格和时序

    I2C详解(4) I2C总线的规范以及用户手册(3) I2C电气规格和时序 I2C详解(1) 一文快速了解I2C的工作原理 I2C详解(2) I2C总线的规范以及用户手册(1) I2C 总线协议 I2 ...

最新文章

  1. 前沿|8种面部表情实时追踪,你的喜怒哀乐全被AI看穿了
  2. QQ群管理员无法进行成员管理问题的解决
  3. JS DATE对象详解
  4. 职场 | 工作五年之后,对技术和业务的思考
  5. 【报告分享】新基建风口下,零售科技企业如何借势发展.pdf(附下载链接)
  6. mysql gtid 双主_MySQL5.7配置GTID双主
  7. 使用js、jquery完成省市二级联动
  8. mysql 分页_MySQL 如何优化大分页查询?
  9. 20170814二维码的识别
  10. 商标45类分类表明细表_商标45类分类表
  11. linux 截取某一段时间的日志,存储到另一个文件中
  12. 2023年基建工程(设计规划施工)经验分享,超多干货
  13. 使用面向对象思想,输出员工信息并计算员工的工资。定义一个部门(Department)类,该类有部门编号(Id)、部门名称(Name)属性;再定义一个员工(Employee)类,该类的属性有员工编号
  14. Math数学工具类在java中如何使用?
  15. 用c语言编写爱心的代码是什么
  16. php artisan tanker,Artisan 开发
  17. 小爬虫爬取小猫咪图片并存入本地文件夹
  18. ESP32运行MicroPython通过MQTT上报温湿度到中移OneNET物联网平台(附源码)
  19. 继续读书 — 《人性的弱点》
  20. 1 个月崩 3 次! 2021 年的 10 个宕机名场面

热门文章

  1. 《Ruminations on C++/C++沉思录》学习笔记一————koening和Moo夫妇访谈
  2. 机器学习与模式识别期末试题回忆
  3. Python利用google翻译,翻译字幕文件!我想翻译日语!
  4. excel教程自学网_超实用!良心推荐15个神级自学网站,内容全面质量又高
  5. itil v4和v3的区别_ITIL从v3到v4 - 这是新的ITIL
  6. MySQL:数据库练习题-3
  7. 你在家看电视,家里的电视也在看你?
  8. RPGViewer - 反馈页面
  9. 解决读取文件乱码问题
  10. 政法委重点人员联防联控系统开发,社会治安防控平台建设