动态规划解决TSP(旅行推销员问题)

2023-10-31

本篇文章参考自https://blog.csdn.net/hu413031273/article/details/51329514
TSP问题(Travelling Salesman Problem)又译为旅行推销员问题、货郎担问题,即假设有一个旅行商人要拜访n个城市,从某个城市出发,每个城市只能访问一次且最后回到出发城市,问该推销员应如何选择路线,才能使总的行程最短?

使用动态规划解决该问题的策略为:

  1. 易知从哪个城市出发其最短路径都是一样的,故假设从城市1出发。假设已经经过了几个城市,我们需要记录此时位于的城市,以及未访问的城市的集合。
  2. 以dp[{V}][init]表示从init点开始,要经过集合V中所有点的距离。dis[init][i]表示城市init到城市i的距离。
    其状态转移方程为dp[{V}][init]=min(dp[{V}][init], dp[{V-i}][i]+dis[init][i])。即假设处于城市init,欲前往下一个城市i,如果在城市i的状态dp[{V-i}][i]加上城市init到城市i的距离小于当前最小值,则前往城市i。
  3. 我们怎么存储未访问的城市的集合?一个方法是以二进制01表示该城市是否被访问过,如s=111110,城市1对应的位为0,其他城市对应的位为1,则表示城市6到城市2都还未访问,城市1已访问过。例如在出发点1时,要判断城市2是否访问过,若s&(1<<1)为1则表示城市2未被访问过,若去城市2,则集合V变为s&(~(1<<1))。
  4. 以数组path[s][init]记录在城市init,未访问城市集合为s时,下一个城市的最优选择,以存储最优路径。

C++代码如下:

#include <iostream>
using namespace std;
int N=6;//点的个数 
int path[1048577][20];//记录路径 
int dp[1048577][20];//2^20=1048576 dp[V][i]表示从点i到访问完集合V所需最短距离 
int dis[20][20]={{0,10,20,30,40,50}, 
					{12,0,18,30,25,21},
					{23,19,0,5,10,15},
					{34,32,4,0,8,16},
					{45,27,11,10,0,18},
					{56,22,16,20,12,0}};//两个城市的距离 
int TSP(int s,int init)
{	
    if(dp[s][init]) return dp[s][init];//如果该状态已计算则直接返回该值 
    if(s==0) return dis[init][0];//如果此时在点init,其他所有点已访问,则返回点init到点1的距离 
    int minlen=100000;
    for(int i=1;i<=N-1;i++){
        if(s&(1<<i)){//如果点i未被访问过 
            if(TSP(s&(~(1<<i)),i)+dis[init][i]<minlen){
                minlen=TSP(s&(~(1<<i)),i)+dis[init][i];
                path[s][init]=i;
            }
        } 
    }
    return dp[s][init]=minlen;
}
int main()
{
    int init=0,s=0; 
	s=0b111110;
    int res=TSP(s,init);
    printf("%d\n",res);
    //打印路径 
    int num=0;
    printf("1 ");
    while(1){
    	printf("%d ",path[s][init]+1);
    	init=path[s][init];
    	s=s&(~(1<<init));
    	num++;
    	if(num>=5){
			break;
		}
	}
	printf("1\n");
} 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

动态规划解决TSP(旅行推销员问题) 的相关文章

  • HDU--1864:最大报销额 DP求最大和(最大和有上限)

    1 题目源地址 http acm hdu edu cn showproblem php pid 1864 2 简要分析 这道题看起来不难 求最大报销额 想法是先找到符合要求的发票 然后求符合要求的发票的最大报销金额 但是 这道题的陷阱好几个
  • (牛客网)华为机试(二)

    牛客网 华为机试题集解答 在解题前先分享一波oj刷题的固定格式代码 方便输入时使用 import java util import java io public class Main 一定要使用Main作为类名 public static
  • 2023华为OD机试真题(java 100%通过)【最多获得的短信条数/动态规划】

    题目内容 某云短信厂商 为庆祝国庆 推出充值优惠活动 现在给出客户预算 和优惠售价序列 求最多可获得的短信总条数 输入描述 第一行客户预算M 其中 0 M 10 6 第二行给出售价表 P1 P2 Pn 其中 1 n 100 Pi为充值 i
  • 入门级动态规划五步法(斐波那契数)

    1 确定dp数组 dp table 以及下标的含义 2 确定递推公式 3 dp数组如何初始化 4 确定遍历顺序 5 举例推导dp数组 class Solution def fib self n int gt int if n 0 retur
  • 删除与获得点数--动态规划

    Leetcode 740 删除与获得点数 题目描述 给定一个整数数组 nums 你可以对它进行一些操作 每次操作中 选择任意一个 nums i 删除它并获得 nums i 的点数 之后 你必须删除每个等于 nums i 1 或 nums i
  • 子串和子序列问题-动态规划向

    1 子串子序列问题概述 有关于子序列和子串的问题是字符串或者数组经常会遇到的问题 一般我们经常使用多指针 滑动窗口 回溯 动态规划的方式去解决 而本篇重点关注能用动态规划解决或者说明显使用动态规划解决的子串问题和子序列问题 1 1 子串 子
  • 2020算法设计与分析 官方考前模拟卷 参考答案

    算法设计与分析 样例试题 算法设计与分析总结笔记 注 此试题仅供了解题型 和期末考试试题没有任何直接关系 FBI Warning 这套题难度较大 千万不要坏了心态 xj大佬说要是考试那么难他直播粪坑蝶泳 Power By 王宏志教授 5 分
  • [leetcode] 推多米诺 双指针

    题目链接 一开始想多了 像成了真实生活中的那种会叠加的状态 就比如 RRL 中 左边的两个 R 会让第三个 L 向右边倾斜 直接用前缀和进行操作 但是发现示例1都无法通过 所以说是错的 正确的想法是 每一个暂未确定状态的 都由这个字符两侧最
  • 最近在学动态规划,很有意思的算法(1)拿金币

    问题描述 有一个N x N的方格 每一个格子都有一些金币 只要站在格子里就能拿到里面的金币 你站在最左上角的格子里 每次可以从一个格子走到它右边或下边的格子里 请问如何走才能拿到最多的金币 输入格式 第一行输入一个正整数n 以下n行描述该方
  • POJ-1458最长公共子序列

    给定序列的子序列是给定序列 其中遗漏了一些元素 可能没有 给定序列X
  • OJ题目8--动态规划问题

    1 509 斐波那契数 力扣 LeetCode leetcode cn com 过去一直用递归法 但由于栈区空间的限制 当递归过深时容易发生栈溢出 int fib int n if n 0 return 0 else if n 1 retu
  • leetcode刷题(77)——312. 戳气球

    一 题目 有 n 个气球 编号为0 到 n 1 每个气球上都标有一个数字 这些数字存在数组 nums 中 现在要求你戳破所有的气球 每当你戳破一个气球 i 时 你可以获得 nums left nums i nums right 个硬币 这里
  • 滑雪(记忆化搜索)

    题目 题解 记忆化搜索模板题 记忆化搜索的核心 本质是带剪枝的深搜 当某点的dp已赋值时 返回该值 其他情况进行深度搜索 模板 dfs u点 if u点的 dp 已经有值了 return u点的 dp 值 else 说明第一次到达u 则为u
  • C++---背包模型---装箱问题(每日一道算法2023.3.9)

    注意事项 本题是 动态规划 01背包 的扩展题 dp和优化思路不多赘述 题目 有一个箱子容量为 V 同时有 n 个物品 每个物品有一个体积 正整数 要求 n 个物品中 任取若干个装入箱内 使箱子的剩余空间为最小 输入格式 第一行是一个整数
  • 字节跳动笔试---字母交换,最多m次

    参考 https blog csdn net cxzzxc123456 article details 79058419 编码题 字符串S由小写字母构成 长度为n 定义一种操作 每次都可以挑选字符串中任意的两个相邻字母进行交换 询问在至多交
  • 蓝桥杯:斐波那契数列最大公约数

    题目表示的很明确 要用两个算法 斐波那契数列是很经典的dp问题 最大公约数是很经典的辗转相除法 从而我理所应当的就定义一个数组存放斐波那契数列 long long int F 2021 0 F 1 1 F 2 1 for int i 3 i
  • 特殊类型动归--区间动归与环形动归

    区间动归 某类有序事件中前若干个事件的子答案 不能再支撑状态转移 我们需要去寻找 从某个元素起到另一个元素结束所包含所有的 连续 元素的子答案 作为状态 可以想象 在这个描述下 每个状态会对应于原题序列上的一个区间 区间具有良好的性质 短的
  • 编程题——连续最大和

    编程题 连续最大和 题目描述 一个数组有 N 个元素 求连续子数组的最大和 例如 1 2 1 和最大的连续子数组为 2 1 其和为 3 输入描述 输入为两行 第一行一个整数n 1 lt n lt 100000 表示一共有n个元素 第二行为n
  • 最大k乘积问题--动态规划

    问题 问题描述 设x是一个n位十进制整数 如果将x划分为k段 则可得到k个整数 这k个整数的乘积称为x的一个k乘积 试设计一个算法 对于给定的x和k 求出x的最大k乘积 编程任务 对于给定的x和k 编程计算x的最大k 乘积 示例 Sampl
  • 超简单:很火的3D立体动态相册,送给心爱的那个人

    1 首先 我们一共需要三个文件 目录关系如下所示 先建index html文件吧 电脑上先创建一个 txt文件 在里面加入代码后保存 重命名为index html 记得把原来的 txt后缀覆盖 html我用的谷歌浏览器 index html

随机推荐

  • javascript函数相关例题

    前言 虽然for也能实现一些简单的 重复操作 但是 比较具有局限性 我们js 里面 也有非常多的相同代码 可能需要大量重复使用 此时我们可以利用函数 一 函数是什么 函数 就是 封装了 一段 可被重复调用执行的 代码块 可以实现大量代码的重
  • 删除git在windows上的凭证

    由于本人安装git的客户端以及开始下载github上的项目代码 第一次输入的账户名以及密码错误 需要删除windows上自己保存的账号密码凭证 我自己的电脑配置 运用命令行打开控制面板也十分方便 快捷键 Win R 打开运行窗口 输入 co
  • vs2010 使用QT

    首先不要使用中文目录 1 下载Qt的安装包和VS2010的Qt插件 2 安装Qt SDK 3 安装Qt的VS开发插件 4 编译Qt Qt默认使用mingw进行编译 如果要使用VS2010开发 需要将Qt重新编译 进入开始菜单Microsof
  • 在VS8里面 fatal error C1083: 无法打开包括文件:“iostream.h”: No such file or directory

    fatal error C1083 无法打开包括文件
  • pointCloudLibrary点云库使用

    pointCloudLibrary点云库使用 准备 下载源码 https github com PointCloudLibrary pcl 这个是pointCloudLibrary 但不包括 Boost Eigen FLANN OpenNI
  • gdb调试子进程

    GDB 是 linux 系统上常用的调试工具 本文介绍了使用 GDB 调试多进程程序的几种方法 并对各种方法进行比较 GDB 是 linux 系统上常用的 c c 调试工具 功能十分强大 对于较为复杂的系统 比如多进程系统 如何使用 GDB
  • 「前端学习」vue入门-井字棋

    1 Vue 学习路线 2 使用 vue cli 创建 vue 项目 注意 vue cli 对应版本 2 1 创建项目 在当前目录下创建项目 vue create 注意 项目文件名不能由大写 2 2 配置 3 Vue 组件 不成问的规定 默认
  • CentOS 安装 Docker 和 DockerCompose,超详细

    0 安装Docker Docker 分为 CE 和 EE 两大版本 CE 即社区版 免费 支持周期 7 个月 EE 即企业版 强调安全 付费使用 支持周期 24 个月 Docker CE 分为 stable test 和 nightly 三
  • [885]Tensorflow设置CUDA_VISIBLE_DEVICES来控制GPU的使用

    os environ CUDA DEVICE ORDER PCI BUS ID 按照PCI BUS ID顺序从0开始排列GPU设备 os environ CUDA VISIBLE DEVICES 0 设置当前使用的GPU设备仅为0号设备 设
  • Java:关于Java中的线程中断的几种方法

    Java 关于Java中的线程中断的几种方法 1 使用线程的stop 来中断线程 2 使用线程的interrupt 来中断线程 3 通过共享变量来控制 使用线程的stop 来中断线程 这种方式是直接调用线程的stop 方法 可以直接让线程终
  • 子网地址,广播地址,子网掩码,主机地址范围,求法总结

    熟练转换 十进制 gt 二进制 如给出 主机数或者说划分多少个子网 这时候 我们用2的n次方 2 gt 主机数或子网数 求出n n表示子网位数 那么子网总数为 2的n次方 而一个字节8位 那么剩下8 n 位主机号 可得出 子网间隔为2的 8
  • NTP-时间同步,(Linux / Windows)服务端搭建到时间同步配置操作-直接拿下

    一 NTP服务器搭建跟同步配置 centos8 1 安装chrony服务 centos8系统版本自带 centos8以前的版本为ntpd服务 yum install chrony 2 启动服务 Systemctl start chronyd
  • MySQL——变量与游标

    今天我们来一起学习MySQL中 的变量 系统变量与用户变量 以及什么是游标 游标如何使用 1 变量 在 MySQL 数据库的存储过程和函数中 可以使用变量来存储查询或计算的中间结果数据 或者输出最终的结果数据 在 MySQL 数据库中 变量
  • 多线程的锁

    简介 1 失败后进行锁膨胀 偏向锁 gt 轻量锁 gt 重量锁 2 偏向锁 认为没有竞争 每次都是同一个线程获取的锁 所以第一次通过CAS后 把线程id放到锁对象Mark Word后 以后每次都不需要CAS操作 3 轻量级锁 认为没有竞争
  • jdbc驱动安装以及简单测试

    最近又需要写jdbc啦 正好顺便把下载配置教程整理一下 教程分三个部分 下载jdbc驱动 配置jdbc到项目 简单连接一下数据库 1 下载jdbc驱动 下载网址 https dev mysql com downloads connector
  • 菜鸟级的Git与GitHub使用总结

    前言 这几天一直在折腾学习Git和GitHub的使用 几天下来 在网上查阅了大量的资料 总算有一些成果 作为一个已经工作两年了的菜鸟程序员 现在才来学习使用Git及github 实在忏愧 网上某大神说的好 不会使用Git和github 根本
  • 史上最牛mysql-02 (MySQL的下载、安装、配置)

    2 MySQL的下载 安装 配置 个人博客 www xiaobeigua icu 2 1 MySQL的4大版本 MySQL Community Server 社区版本 开源免费 自由下载 但不提供官方技术支持 适用于大多数普通用户 MySQ
  • chrome 该文件可能已遭到删除、移动,或者文件权限不允许进行访问

    最新 我他妈的直接拖到浏览器里 貌似就好了 下边也操作过 不知道是否有影响 草草草草 创建MyChromeDevUserData的文件夹 打开终端 输入下面的命令 需要替换路径中的yourname open n Applications G
  • springboot整合ELK快速搭建日志管理系统

    一 ELK简介 ELK是Elastic公司的三个组件 三个组件共同配合实现日志收集 Elasticsearch是实时全文搜索和分析引擎 提供搜集 分析 存储数据三大功能 是一套开放REST和JAVA API等结构提供高效搜索功能 可扩展的分
  • 动态规划解决TSP(旅行推销员问题)

    本篇文章参考自https blog csdn net hu413031273 article details 51329514 TSP问题 Travelling Salesman Problem 又译为旅行推销员问题 货郎担问题 即假设有一