由旅行商问题认识何为状态压缩

动态规划

动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。20世纪50年代初美国数学家R.E.Bellman等人在研究多阶段决策过程(multistep decision process)的优化问题时,提出了著名的最优化原理(principle of optimality),把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解,创立了解决这类过程优化问题的新方法——动态规划。

https://blog.csdn.net/hebtu666/article/category/8018091基础总结

 

状态压缩

我们在进行动态规划时,有时状态相当复杂,看上去需要很多空间,比如一个数组才能表示一个状态,那么就需要对状态进行某种编码,进行压缩表示。

比如:状态和某个集合有关,集合里可以有一些元素,没有另一些元素,那么就可以用一个整数表示该集合,每个元素对应于一个bit,有该元素,则该bit就是1。

这个皇后问题就可以帮助理解https://blog.csdn.net/hebtu666/article/details/84631083

 

旅行商问题

 

旅行商问题(TravelingSalesmanProblem,TSP)是一个经典的组合优化问题。经典的TSP可以描述为:一个商品推销员要去若干个城市推销商品,该推销员从一个城市出发,需要经过所有城市后,回到出发地。应如何选择行进路线,以使总的行程最短。从图论的角度来看,该问题实质是在一个带权完全无向图中,找一个权值最小的Hamilton回路。由于该问题的可行解是所有顶点的全排列,随着顶点数的增加,会产生组合爆炸,它是一个NP完全问题。由于其在交通运输、电路板线路设计以及物流配送等领域内有着广泛的应用,国内外学者对其进行了大量的研究。早期的研究者使用精确算法求解该问题,常用的方法包括:分枝定界法、线性规划法、动态规划法等。但是,随着问题规模的增大,精确算法将变得无能为力,因此,在后来的研究中,国内外学者重点使用近似算法或启发式算法,主要有遗传算法、模拟退火法、蚁群算法、禁忌搜索算法、贪婪算法和神经网络等。

 

如图,我们如何从0点出发,以最小代价走过所有的点?

 

分析

 

抛开这个图,我们试想:我们可能从0点一次性走到哪些点呢?

只可能1点、2点、3点、4点(废话)

我们如果知道了

1)从1点开始走,经过所有的点,最后走到了0点的最小距离;a

2)从2点开始走,经过所有的点,最后走到了0点的最小距离;b

3)从3点开始走,经过所有的点,最后走到了0点的最小距离;c

4)从4点开始走,经过所有的点,最后走到了0点的最小距离;d

请再次注意:

我们可能从0点一次性走到哪些点呢?

只可能1点、2点、3点、4点(废话)

所以我们可以从0点走到1点,再从1点经过最小距离走到0点。

2点、3点、4点同理。

那么我们取min(a+3,b+MAX,c+4,d+MAX)即可。

3为0点走到1点的距离,4为0点走到3点的距离。

MAX代表此路不通。。

 

那我们继续思考,abcd怎么求呢?其实同样的:

 

比如:求a

从1点开始走,经过所有的点,最后走到了0点的最小距离;a

同样的思考:我们可能从1点一次性走到哪些点呢?

答:可以走到0点、2点、3点、4点。

注意:由于问题要求为:只能经过每一个顶点一次,所以我们要去掉0点,因为我们经过0点,最后再到0点就会重复,所以,

“经过所有的点”是不准确的,是除0点的所有的点。

所以只有三个点可能从1点走过去,我们需要求:

1)从2点开始走,经过除0点所有的点,最后走到了0点的最小距离x

2)从3点开始走,经过除0点所有的点,最后走到了0点的最小距离y

3)从4点开始走,经过除0点所有的点,最后走到了0点的最小距离z

然后取min(x+到2点的距离,y+到3点的距离,z+到4点的距离)

 

归纳表达式

1)我们会发现,每一次状态转移其实对应的是一个点的集合:

以后还会有经过除1,2点,经过除1,2,3点等等。

 

2)还有从哪个点开始走:

这两个条件就可以描述当前的状态。

我们把上面的总结用公式表示出来:

S为已经访问过的点的集合

v表示当前所在点。

那么dp[S][v]就表示为从点v出发访问剩余点,最终返回0点的最小长度。

我们把刚才的求解过程用公式表达出来。

dp[S][v]=min(dp[S\bigcup {u}][u]+d(v,u)\mid u\euro S)

∉这个符号我实在没找到,理解意思。

 

压缩

像这样,状态可以根据集合表示的DP,我们称作状态压缩DP。

状态和某个集合有关,集合里可以有一些元素,没有另一些元素,那么就可以用一个整数表示该集合,每个元素对应于一个bit,有该元素,则该bit就是1。 

本题来说,所有点都在集合里就是11111

哪个点没在,对应的位就为0

 

注意:对于状态不是整数而是集合的情况,通常不太容易确定DP的顺序,如果确实不好想顺序,可以通过记忆化搜索来做。

集合S,如果对于任意S(i)<S(j),那么一定有i<j。所以确定了顺序。

 

确定dp表的大小,有n个城市,从0开始编号,那么dp表的行数就是n,列数就是2^(n-1)

int n;
int d[MAX_N][MAX_N];//邻接矩阵
int dp[1<<MAX_N][MAX_N];

对于数字x,要看它的第i位是不是1,那么可以通过 (x >>i) & 1取出那一位来看

先用足够大的值初始化dp数组,不要影响结果,然后核心代码:

for(int S = (1<<n)-2 ; S >= 0 ; s--)//每一个集合
{for(int v = 0 ; v < n ; v++)//每一个出发点{for(int u = 0 ; u < n ; u++)//访问每一个点{if(!(S>>u&1))//判断是否在集合中{dp[S][v] = min(dp[S][v] , dp[S | 1<<u][u]+d[v][u]);}}}
}

 

总结

 

当我们把状态压缩应用到动态规划中,可以用来精简状态,节约空间,也方便转移。

最常见的就是用二进制来表是状态,利用各种位移运算,就可以实现O(1)的转移。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/445465.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++基础学习(06)--(时间,输入输出,数据结构)

文章目录目录1.时间2.输入输出数据结构目录 1.时间 当前日期和时间 下面的实例获取当前系统的日期和时间&#xff0c;包括本地时间和协调世界时&#xff08;UTC&#xff09;。 #include <iostream> #include <ctime>using namespace std;int main( ) {// 基于当前…

Abstract Self-Balancing Binary Search Tree

二叉搜索树 二叉查找树&#xff08;Binary Search Tree&#xff09;&#xff0c;&#xff08;又&#xff1a;二叉搜索树&#xff0c;二叉排序树&#xff09;它或者是一棵空树&#xff0c;或者是具有下列性质的二叉树&#xff1a; 若它的左子树不空&#xff0c;则左子树上所有结…

AVL Tree

前言 希望读者 了解二叉搜索树 了解左旋右旋基本操作 https://blog.csdn.net/hebtu666/article/details/84992363 直观感受直接到文章底部&#xff0c;有正确的调整策略动画&#xff0c;自行操作。 二叉搜索树 二叉查找树&#xff08;Binary Search Tree&#xff09;&a…

c++基础学习(07)--(类)

文章目录目录类与对象1.类成员函数2.类访问修饰符3.构造函数与析构函数4.拷贝构造函数5. 友元函数6.内联函数7.this指针8.指向类的指针9.类的静态成员目录 类与对象 #include <iostream>using namespace std;class Box {public:double length; // 长度double breadth;…

c++基础学习(08)--(继承、重载、多态、虚函数)

文章目录目录1.继承2.重载3.多态 && 虚函数目录 1.继承 #include <iostream>using namespace std;// 基类 class Shape {public:void setWidth(int w){width w;}void setHeight(int h){height h;}protected:int width;int height; };// 派生类 class Rectang…

图的应用

1. 图的应用总览 在数据结构中图的应用很广泛&#xff0c;本文主要从以下四个方面介绍&#xff1a; ①最小生成树&#xff1a;给定一个无向网络&#xff0c;在该网的所有生成树中&#xff0c;使得各边权数之和最小的那棵生成树称为该网的最小生成树&#xff0c;也叫最小代价…

c++基础学习(09)--(数据抽象、数据封装、接口)

文章目录目录1.数据抽象2.数据封装3.抽象接口类目录 1.数据抽象 数据抽象&#xff1a;就是把它当做黑箱子使用&#xff0c;内部实现与外部接口分开 C类实现数据抽象&#xff0c;如sort()函数&#xff0c;ostream的cout对象 #include <iostream> using namespace std…

c++基础学习(10)--(文件、流、异常处理、动态内存、命名空间)

文章目录目录1.文件和流2.异常处理3.动态内存4.命名空间目录 1.文件和流 注意 文件打开方式中的in和out都是相对于内存&#xff08;计算机&#xff09;而言的&#xff0c;计算机读取文件&#xff0c;是将数据从磁盘中的文件读入到内存中&#xff0c;所以用的是in #include &…

数据结构和算法(02)---字符串(c++)

文章目录目录一.c风格的字符串与操作函数1.c风格字符串2.c风格字符串处理函数二.c中的字符串与操作函数1.c中的string类2.string类的基本操作3.string类的操作汇总目录 数据结构&#xff1a; 逻辑结构&#xff1a;数组&#xff0c;栈&#xff0c;队列&#xff0c;字符串&#x…

如何学习数据结构和算法——大佬文章汇总

第一篇 第二篇、 作者&#xff1a;左程云 我分别说一下国内和国外的行情。 国内的话&#xff0c;一般来讲&#xff0c;工资高的公司在面试时算法和数据结构题目的比重较大&#xff0c;工资一般的公司比重较小。当然同样公司的不同岗位&#xff0c;要求也会不同&#xff0c;…

c++基础学习(13)--(STL、标准库)

文章目录目录1. STL教程2.标准库3.有用的资源目录 1. STL教程 #include <iostream> #include <vector> using namespace std;int main() {// 创建一个向量存储 intvector<int> vec; int i;// 显示 vec 的原始大小cout << "vector size " &…

哈夫曼实现文件压缩解压缩(c语言)

写一个对文件进行压缩和解压缩的程序&#xff0c;功能如下&#xff1a; ① 可以对纯英文文档实现压缩和解压&#xff1b; ② 较好的界面程序运行的说明。 介绍哈夫曼&#xff1a; 效率最高的判别树即为哈夫曼树 在计算机数据处理中&#xff0c;霍夫曼编码使用变长编码表对源…

c++基础学习(11)--(模板、预处理器、信号处理)

文章目录目录1.模板2.预处理器3.信号处理目录 1.模板 模板是泛型编程的基础&#xff0c;泛型编程&#xff1a;以一种独立于任何特定类型的方式 #include <iostream> #include <string>using namespace std;template <typename T> inline T const& Max…

c++基础学习(12)--(多线程、Web编程)

文章目录目录1.多线程2.web编程目录 1.多线程 #include <iostream> // 必须的头文件 #include <pthread.h>using namespace std;#define NUM_THREADS 5// 线程的运行函数 void* say_hello(void* args) {cout << "Hello Runoob&#xff01;" <&…

《Head First设计模式》第九章(1)迭代器模式

迭代器模式 因为这一章涉及到两个模式&#xff0c;内容有点多&#xff0c;还有一个组合模式留到下一篇写吧。 有许多种方法可以把对象堆起来成为一个集合&#xff08;collection&#xff09;。你可以把它们放进数组、堆栈、列表或者是散列表&#xff08;Hashtable&#xff09…

索尼XB950N1 震撼人心的重低音

虽然题目是震撼人心的重低音&#xff0c;但是低音可以通过app调节&#xff0c;所以我们可以用这个耳机听各种类型的歌曲。 索尼XB950N1与XB950B1非常相似&#xff0c;但索尼XB950N1提供了主动降噪&#xff0c;续航稍长一些。从蓝牙3.0升级到了蓝牙4.1&#xff0c;改善了传输范…

数据结构和算法(04)---数组,动态内存,vector(c++)

文章目录目录数组1.数组的申明2.数组的初始化3.二维数组4.指向数组的指针5.传递数组给函数动态内存1.new &#xff0c;delete运算符2.数组的动态内存分配vector1.vector基本操作2.vector使用3.vector动态二维数组 初始化和赋值目录 数据结构&#xff1a; 逻辑结构&#xff1a;数…

数据结构和算法(05)---链表(c++)

文章目录目录链表的基本概念1.数组和链表链表的使用1.链表的简单使用2.链表的进阶使用3.链表的高阶使用4.链表的其他操作链表容器list1.list介绍2. list使用3. list与vector之间的区别4.list例子代码目录 数据结构&#xff1a; 逻辑结构&#xff1a;数组&#xff0c;栈&#xf…

论文阅读 状态压缩

状态压缩 Abstract 信息学发展势头迅猛&#xff0c;信息学奥赛的题目来源遍及各行各业&#xff0c;经常有一些在实际应用中很有价值的问题被引入信息学并得到有效解决。然而有一些问题却被认为很可能不存在有效的(多项式级的)算法&#xff0c;本文以对几个例题的剖析&#xf…

数据结构和算法(06)---二叉树(c++)

文章目录目录二叉树1.二叉树的基本概念2.二叉树的应用和时间复杂度3.二叉树的插入4.二叉树的查找5. 二叉树的遍历6.二叉树的删除二叉树的基本操作1.二叉树的基础操作2.代码实现创建二叉树和三种遍历二叉树的方法目录 数据结构&#xff1a; 逻辑结构&#xff1a;数组&#xff0c…