什么是状态压缩DP???

news2024/12/26 0:12:09

1. 引言

相信大家已经对普通的01背包或者其他背包问题已经很熟练了,但是有时候我们去解决NP问题(指数级别的复杂度,比如N!),时间复杂度就会非常之大

所以,这个时候我们需要寻找更加优化的方法,来优化DP

状态压缩也是一种DP优化方法

2. 什么是状态压缩?

状态压缩:是一种优化动态规划算法的技术,通常用于解决具有大量状态的问题,以减少内存消耗和提高计算效率。在动态规划问题中,状态通常是指描述问题的各种情况或者组合的变量,而状态压缩就是通过一种巧妙的方式来表示和存储状态,从而减少内存消耗。

也就是说,当DP状态是集合的时候,把集合的组合或者排列用二进制进行表示,这个二进制01组合表示集合的的一个子集 , 可以将DP状态的处理转成为二进制的位操作,能够提高算法的效率

当一个DP具有以下特征的时候,就适合用状态压缩了:

  1. 状态之间存在某种转移关系,但状态数量巨大。
  2. 状态之间的转移可以通过位运算来表示。
  3. 状态之间的转移关系可以通过枚举子集或者排列组合的方式来计算。

3. 引子

现在,我们来看一道经典问题,一起学习什么是状态压缩。

给定一张 n个点的带权无向图,点从 0∼n−1标号,求起点 0到终点 n−1 的最短 Hamilton 路径。

Hamilton 路径的定义是从 0到 n−1不重不漏地经过每个点恰好一次。

输入格式
第一行输入整数 n。

接下来 n行每行 n个整数,其中第 i行第 j个整数表示点 i到 j的距离(记为 a[i,j])。

对于任意的 x,y,z,数据保证 a[x,x]=0,a[x,y]=a[y,x] 并且 a[x,y]+a[y,z]≥a[x,z]。

输出格式
输出一个整数,表示最短 Hamilton 路径的长度。

数据范围
1≤n≤20

0≤a[i,j]≤107

输入样例:
5
0 2 4 5 1
2 0 6 5 3
4 6 0 8 3
5 5 8 0 5
1 3 3 5 0


输出样例:
1

Hamilton(旅行商)是一个NP问题,N个点的全排列,时间复杂度是n!这是非常之大的。

有人看到最短路或许会无脑dijkstra, 但是对于dijkstra求最短路是并没有考虑每个点的

这道题的难度就在每个点都需要访问一次,所以并不能适用

就算使用回溯搜索,那也非常大的时间复杂度

4. DP求解Hamilton问题

4.1 状态定义

如何进行DP状态定义,这是我们首要解决的

DP问题,无非就是从小问题递推到大问题,那么我们可以这样进行dp定义:

dp[s][j]:代表在S集合内,到达j点的最短距离(j也在S集合内,因为每个点都需要到达)

我们可以通过子集然后递推求出大集合

4.2 属性定义

这道题很明确,其实就是求最小值,也就是min

4.3 状态转移

从集合S到j点的最短距离,无非就是需要从前面的集合开始入手

我们可以从小问题S-j递推到大问题S

S-j:代表从集合S中去除j点的集合

如何从S-j递推到S又是一个难题,我们可以设k为S-j中的一个点,把0~j 分为两个部分:

第一部分就是:0->k , 第二部分是k->j

我们先到k点,然后从k点到j点,于是就有了以下状态转移方程式

dp[S][j] = min(dp[S - j][k] + dist[k][j])

dist[k][j]:k到j的距离

这个地方会比较难以理解,但是要清楚:DP就是从小问题递推到大问题

我们要求S集合内到达j点的最短路,无非就是要从S中把j点去除,然后通过中间的那些点作为媒介,一个一个递推到S -> j

 5. 代码

知道这些,我们可以开始编码了:

解析:

  • 状态压缩,是将一个二进制数表示一个集合S,二进制的每一位都代表图上的每一个点。
  • 对于二进制位每一位来说,有1就代表全都有,比如n = 5时,二进制为:11111 , 也就代表这个集合里面有1、2、3、4、5几个点
from math import *

n = int(input())

dist = [[0] * (n + 1) for i in range(n + 1)]    # 两个点之间的距离
for i in range(n):
    a = list(map(int, input().split()))
    for j in range(len(a)):
        dist[i][j] = a[j]

# 集合S到j的最短距离 , 这里的1 << 20是因为题目的范围是1 - 20 , 最大只有20个点,通过位运算的形式,将这21个点转为集合
dp = [[inf] * (n + 1) for i in range(1 << 20)]   # 初始化都是最大的


dp[1][0] = 0  # 最开始,集合里面只有一个0点
for s in range(1 << n):    # 二进制总共的位数
    for j in range(n):
        if (s >> j) & 1:   # 判断j是否在S中
            for k in range(n):
                if (s ^ (1 << j)) >> k & 1:   # 判断k是否在S除去j里面

                    dp[s][j] = min(dp[s][j], dp[s ^ (1 << j)][k] + dist[k][j])  # 状态转移方程

print(dp[(1 << n) - 1][n - 1]) 

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

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

相关文章

微信小程序调试、断点调试

1、wxml 查看对应的页面组件 2、console面板可以用来打印信息 3、sources 用来断点调试 4、network面板用来调试接口 5、storage面板 可以查看每个key对应的value内容&#xff0c;这些数据在用户使用小程序时被持久化保存在本地。

Java基础之多线程

多线程 一、多线程的创建1.1 方式一 继承Thread类1.2 方式二 实现Runnable接口1.3 方式二的化简(匿名内部类)1.4 实现Callable接口(JDK5新增)1.5 小节 二、Thread常用API2.1 获取当前线程对象2.2 获取/设置线程名称2.3 Thread的构造器2.4 Thread类的线程休眠方法2.5 小节 三、线…

3 CUDA硬件概述

3.1 PC 架构 首先&#xff0c;我们看看当下许多PC中都使用的酷睿2(Core2)处理器的典型架构&#xff0c;然后分析一下它是如何影响我们使用GPU 加速器的(如图 3-1所示)。 图3-1典型的酷睿2(Core2)系列处理器的结构图 由于所有的 GPU 设备都是通过 PCI-E(Peripheral Communicat…

【教程】如何自制一个ArcGIS工具箱

ArcGIS已经提供了十分丰富的工具箱&#xff0c;但是如果遇到一些需要批处理或者需要将多个工具箱组合使用&#xff0c;就需要根据需求自制一个ArcGIS的工具箱。 下面介绍一下如何自制一个ArcGIS/ArcGIS Pro工具箱&#xff0c;主要是使用ArcPy和模型构建器。 使用模型构建器 使…

给计算机专业学生的建议

如果条件允许&#xff0c;推荐尝试考研。虽然研究生学历的价值在一定程度上有所下降&#xff0c;但计算机专业研究生的发展前景通常优于本科生。如果决定考研&#xff0c;应尽力提高自己的学校等级。比赛成绩对于求职帮助有限&#xff0c;除非是含金量高的比赛&#xff0c;通常…

隐语笔记1 —— 数据可信流通,从运维信任到技术信任

数据可信流通体系 关于可信的反思 信任是涉及交易或交换关系的基础 信任的基石&#xff1a; 身份可确认利益可依赖能力有预期行为有后果 数据流通中的不可信风险&#xff1a;可信链条失效&崩塌 法规层面&#xff1a;数据的持有权&#xff0c;加工权&#xff0c;经营权…

FPGA学习_时序约束以及VIVADO时序报告

文章目录 前言时序约束的目的一、时序约束种类1、约束主时钟2、约束衍生时钟3、约束虚拟时钟4、input delay5、output delay6、约束异步时钟组7、约束互斥时钟8、假路径约束9、多周期约束 二、VIVADO时序报告三、从时序的角度看为什么寄存器赋值慢一拍 前言 一边学习一边补充当…

Unity Toggle与Toggle Group的妙用

Toggle与Toggle Group结合使用&#xff0c;妙处多多。 因为在同一Toggle Group内只有一个Toggle可以被选中&#xff0c;那么对于我们要创建单选按钮组、游戏的一些开关、暗夜模式、筛选不同显示内容等功能都非常好用。 比如我要实现通过点击不同按钮,从而筛选显示不同内容&am…

IO扩展芯片应用及方案选型 (74HC595,74HC165,8255,CH351等)

IO扩展芯片应用及方案选型 (74HC595,74HC165,8255,CH351等) 参考书籍《振南技术干货集&#xff1a;单片机–基础进阶创业十年》作者&#xff1a;于振南 在我们进行单片机开发的时候, 经常会发现I/O 口不够用。 一方面是因为我们产品中往往都包括很多的功能, 又有显示, 又有存储…

uniapp,导航栏(切换项)有多项,溢出采取左滑右滑的形式展示

一、实现效果 当有多项的导航&#xff0c;或者说切换项&#xff0c;超出页面的宽度&#xff0c;我们采取可滑动的方式比较好一些&#xff01;并且在页面右边加个遮罩&#xff0c;模拟最右边有渐变效果&#xff01; 二、实现代码 html代码&#xff1a; <!-- 头部导航栏 --…

探究Kafka主题删除失败的根本原因

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 探究Kafka主题删除失败的根本原因 前言主题删除的基础主题删除的定义和作用&#xff1a;删除操作的基本流程&#xff1a; 可能存在删除异常的因素数据积压的处理方法Broker状态异常处理方法通用方法 前…

PyTorch 深度学习(GPT 重译)(一)

第一部分&#xff1a;PyTorch 核心 欢迎来到本书的第一部分。在这里&#xff0c;我们将与 PyTorch 迈出第一步&#xff0c;获得理解其结构和解决 PyTorch 项目机制所需的基本技能。 在第一章中&#xff0c;我们将首次接触 PyTorch&#xff0c;了解它是什么&#xff0c;解决了…

【JS】数组查重

码 /*** 数组查重* param {Array} arr 查重的数组* returns Array 返回不重复的数组 */ const noReArr arr > [...new Set(arr)]const a [12,12,3,4] console.log( noReArr(a) );效果图

使用STM32 再实现电动车防盗

项目需求 点击遥控器 A 按键&#xff0c;系统进入警戒模式&#xff0c;一旦检测到震动&#xff08;小偷偷车&#xff09;&#xff0c;则喇叭发出声响报警&#xff0c; 吓退小偷。 点击遥控器 B 按键&#xff0c;系统退出警戒模式&#xff0c;再怎么摇晃系统都不会报警&…

vscode搜索总是搜到修改记录文件如何处理

如图每次搜索出来的结果总是有好多编辑记录中的文件&#xff0c;给自己找文件及提交代码时带来很大困扰&#xff0c;每次都得删特别麻烦。 解决办法&#xff1a; 如上图在插件里找到 local history 点击 ”禁用“ 即可。以后再编辑代码就不会产生修改记录文件了。 如果直接搜索…

【matlab安装casadi】

虽然安装起来很简单&#xff0c;但是网上没找到好的教程&#xff0c;姑且写一下记录一下 首先到github找到对应的库&#xff1a;https://github.com/casadi/casadi找到发布的版本&#xff0c;点进去 这里就可以点进去下载自己需要的版本了下面也有对应的下载后的安装方式&…

ArcGIS Pro与R:携手优化生态系统服务评估流程

生态系统服务是指生态系统所形成的用于维持人类赖以生存和发展的自然环境条件与效用&#xff0c;是人类直接或间接从生态系统中得到的各种惠益。联合国千年生态系统评估&#xff08;Millennium ecosystem assessment&#xff0c;MA&#xff09;提出生态系统服务包括供给、调节、…

linux系统--------------mysql数据库管理

目录 一、SQL语句 1.1SQL语言分类 1.2查看数据库信息 1.3登录到你想登录的库 1.4查看数据库中的表信息 1.5显示数据表的结构&#xff08;字段&#xff09; 1.5.1数据表的结构 1.5.2常用的数据类型: 二、关系型数据库的四种语言 2.1DDL&#xff1a;数据定义语言&am…

【堆】Top-K问题

标题&#xff1a;C语言库函数scanf&#xff08;&#xff09;解读 水墨不写bug &#xff08;图片来源于网络&#xff09; 正文开始&#xff1a; Top-K问题是一类问题的统称&#xff1a; 即根据对象的某一属性&#xff0c;找出这个属性最突出的K个对象&#xff0c;并且通常对象…

Midjourney发布新特性风格参考

1. 引言 最近&#xff0c;Midjourney 推出了Style Reference V2.0 即功能更加强大的风格参考工具&#xff0c;该工具可以让大家参考其他图像的风格&#xff0c;生成与参考图像风格保持一致&#xff0c;与文本提示词语义内容保持一致的图像。它与图像提示类似&#xff0c;但是只…