动态规划算法:状态压缩

状态压缩动态规划算法

状态压缩动态规划是动态规划的一种,它通过使用位运算的方式压缩程序占用的空间,对于可以用来解决一些只有两个状态(是与否)的问题。
多少无益,我们通过下面的一道编程题目来学习这种算法。

题目描述:
小明使用霰弹枪打固定靶,假设有M个目标,小明开了N枪。每一枪都有若干目标被命中。现在小明想知道,自己刚刚理论上最少只需要几枪就能打中全部的目标。

假设有3个目标:[0, 0, 0]
小明开了3枪:[1, 0, 0],[0, 1, 0],[0, 1, 1],其中为1表示命中了对应的目标。
结果输出:小明第一枪加第三枪命中了所有的目标,理论上只要两枪就可以全部命中。

假设有3个目标:[0, 0, 0]
小明开了3枪:[1, 0, 0],[0, 1, 0],[1, 1, 0],其中为1表示命中了对应的目标。
结果输出:小明无法全部命中目标。

分析:
这道题有很多不同解法,可以使用贪心算法,但是为了讲解状压动规,这里不使用贪心算法。
使用动态规划解决问题的第一步就是要确定使用动态规划能否解决问题。题干中有一个关键词,最少几枪。更关键的一点是它没有要求我输出到底是哪几枪(如果要求输出哪几枪可能就要用回溯子集了)。因此大家应该条件反射的尝试使用动态规划。
动态规划最重要的一个步骤就是确定动态数组dp与状态转移矩阵。

确定dp数组的含义
首先确认dp的大小,有的同学可能条件反射的认为dp的大小应该是M,对应M个目标。dp[i]表示命中i个目标需要的最小枪数。但是接下来会发现举步维艰,因为都是命中i个目标,如果打中不一样的靶子,反应的是不同的状态。实际上这道题的dp矩阵的索引的含义并不是直接了当的呈现在我们的面前。
提问:当我有M个目标时,我有多少种命中状态?
答:每个目标都有命中与未命中两种状态,M个目标组合起来应该是2的M次方。
在这里插入图片描述
聪明的读者到这里应该恍然大悟一下:原来dp要有2^M个元素,索引反应了目标的命中情况。假设dp[3] = 2,indx = 3的二进制是011b,这里表示命中前两个目标最少需要2枪。

dp数组初始化
明确了dp数组的含义,就需要对dp数组进行初始化了,结合dp数组的含义,我们应该首先明确:
dp[0] = 0:命中0个目标需要开0枪。
假设小明第2枪命中情况为:[1, 0, 1],那么:
dp[101b] = dp[5] = 1:命中第一个与第三个目标只需要一枪。
我们将命中目标用二进制掩码表示,将所有子弹命中的情况对应的dp[indx]置为1即可完成初始化。
这就是这个问题的解决思路,现在我们直接上代码,一些细节用代码来讲述。

完整代码

#include <iostream>
#include <vector>
#include <string>
#include <climits>
using namespace std;int main() {int M, N;		// M个目标 开N枪cin >> M >> N;	// 输入 M 与 Nvector<int> state;	// 装填掩码for (int i = 0; i < N; i++) {int s = 0;for (int j = 0; j < M; j++) {int tmp = 0;cin >> tmp;		//  输入第i枪命中情况,1:命中,0:未命中s = (s << 1) + tmp;}state.push_back(s);}// 对state内的所有数据按位取与,如果tmp = 2^M -1,证明N枪后所有目标都命中int tmp = 0;for (int i : state) {tmp |= i;}if (tmp != (1 << M) - 1) {	cout << "未命中所有目标" << endl;return 0;}// 初始化dp数组int num = (1 << M) - 1;vector<int> dp(num + 1, INT_MAX);dp[0] = 0;for (int i : state) {dp[i] = 1;}// 状态转移,讲解见后文for (int mask : state) {for (int indx = num; indx >= 0; indx--) {if (dp[indx] != INT_MAX) {int new_indx = indx | mask;if (dp[indx] + 1 < dp[new_indx]) {dp[new_indx] = dp[indx] + 1;}}}}cout << "最少需要" << dp[num] << "枪" << endl;return 0;
}

状态转移分析

假设当前命中状态为x0,在第k发子弹的射击下,命中状态x1变为x1 = x0 | state[k];
从状态x0到状态x1,射击次数变为:tmp_num = dp[x0] + 1
结合dp[x1]的定义:命中状态为x1时,需要最少的的射击次数。因此我们需要比较通过x0转移到x1的射击次数tmp_numdp[x1]目前的值:
伪代码:

int x1 = x0 | state[k];	// 这里表示一次射击动作
int tmp_num = dp[x0] + 1;
if(tmp_num < dp[x1]) { dp[x1] = tmp_num;	// 证明由x0到达x1比原本的方案更快 }
else { ;	// 空操作,证明当前到达x1有更快的射击方案 }

小结

上面的讲解就是状态压缩动态规划的一个使用案例与核心逻辑。
之所以选择这种方法有三个关键要素:
1、求最优方案。
2、不要求输出最优方案的具体路径信息。
3、对于最小元素(一个目标),只有是和否(命中/未命中)两种区别。

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

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

相关文章

查看matlab函数帮助文档的方法

方法一&#xff1a;在命令行窗口中使用help命令 方法二&#xff1a;在命令行窗口中使用doc命令 方法三&#xff1a;在帮助文档中搜索关键字

MYSQL初阶(暂为自用草稿)

目录 基本操作 database操作 table操作 数据类型 INT类型 bit类型 FLOAT类型 CHAR类型 DATE类型 SEL类型 表的约束 列约束 NULL DEFAULT PRIMARY KEY UNIQUE KEY 表约束 PRIMARY KEY FOREIGN KEY 其他补充 AUTO_INCREMENT COMMENT ZEROFILL 表的CRUD …

MVC/MVVM 高级应用的深度解析

状态共享与同步 跨组件状态管理策略 状态变更的传播机制优化 状态快照与时间旅行调试 状态持久化 本地存储策略 状态序列化与反序列化 与服务端状态同步 数据绑定进阶 双向绑定优化 脏检查机制优化 基于Proxy/Object.defineProperty的实现差异 批量更新策略 自定义…

AI 边缘计算盒子:开启智能物联新时代

一、什么是 AI 边缘计算盒子 AI 边缘计算盒子是一种集成了高性能芯片、AI 算法和数据处理能力的硬件设备。它部署在数据源的边缘侧&#xff0c;如工厂、商场、交通路口等&#xff0c;能够在本地进行数据采集、预处理、分析和决策&#xff0c;而无需将所有数据上传到云端。这种…

LeetCode 5:最长回文子串

1、题目描述 给你一个字符串 s&#xff0c;找到 s 中最长的 回文 子串。 示例 1: 输入&#xff1a;s "babad" 输出&#xff1a;"bab" 解释&#xff1a;"aba" 同样是符合题意的答案。 示例 2: 输入&#xff1a;s "cbbd" 输出&#…

简易 Python 爬虫实现,10min可完成带效果源码

目录 准备工作 编写爬虫代码 运行爬虫 查看结果 遇到的问题及解决 总结 前言和效果 本文记录了使用 Python 实现一个简单网页爬虫的过程&#xff0c;目标是爬取 quotes.toscrape.com 的名言和作者&#xff0c;并将结果保存到文本文件。以下是完整步骤&#xff0c;包含环境…

【KWDB 创作者计划】_上位机知识篇---Docker容器

文章目录 前言1. Docker 容器是什么&#xff1f;隔离性轻量级可移植性可复用性 2. Docker 核心概念镜像容器仓库Dockerfile 3. Docker 基本使用(1) 安装 Docker(2) 容器生命周期管理(3) 镜像管理(4) 进入容器内部(5) 数据持久化&#xff08;挂载卷&#xff09;(6) 网络管理 4. …

树莓派练习

1.守护进程 守护进程含义&#xff1a;守护进程在树莓派上电后开始运行&#xff0c;断电后结束运行的进程&#xff0c;即使你的终端退出也不会停止&#xff0c;我们可以手动关闭它 使用nohup创建守护进程 先创建一个c语言文件&#xff08;long_task.c&#xff09; #include …

详细解释浏览器是如何渲染页面的?

渲染流程概述 渲染的目标&#xff1a;将HTML文本转化为可以看到的像素点 当浏览器的网络线程收到 HTML 文档后&#xff0c;会产生一个渲染任务&#xff0c;并将其传递给渲染主线程的消息队列。在事件循环机制的作用下&#xff0c;渲染主线程取出消息队列中的渲染任务&#xff0…

java+postgresql+swagger-多表关联insert操作(九)

入参为json&#xff0c;然后根据需要对多张表进行操作&#xff1a; 入参格式&#xff1a; {"username": "车主01","usertel": "11111111111","useridtype": "2","useridcard": null,"proname&qu…

JavaSpring 中使用 Redis

创建项目 配置 Redis 服务地址 创建 Controller 类 由于当前只是些简单的测试代码&#xff0c;所以就不进行分层了&#xff0c;只创建一个 Controller 来实现 jedis 通过 jedis 对象里的各种方法来操作 Redis 此处通过 StringRedisTemplate 来操作 Redis 最原始提供的类是 Re…

AI文生图工具推荐

一、AI文生图技术实现原理 AI文生图&#xff08;Text-to-Image&#xff09;基于生成对抗网络&#xff08;GAN&#xff09;或扩散模型&#xff08;Diffusion Model&#xff09;实现&#xff0c;通过深度学习将文本描述转化为图像。其核心流程包括&#xff1a; 文本编码&#xf…

数据结构——快排和归并排序(非递归)

快速排序和归并排序一般都是用递归来实现的&#xff0c;但是掌握非递归也是很重要的&#xff0c;说不定在面试的时候面试官突然问你快排或者归并非递归实现&#xff0c;递归有时候并不好&#xff0c;在数据量非常大的时候效率就不好&#xff0c;但是使用非递归结果就不一样了&a…

【笔记】网络安全管理

计算机硬件中,运算器和控制器通常集成在一块芯片内,一般称为()。 数据库DB、数据库系统DBS、数据库管理系统DBMS,三者之间的关系是()。 OSI/RM体系结构中的网络层与TCP/IP体系结构中的()功能相同。 三级系统应按照等保2.0要求采用密码技术通信过程中数据的()。 …

.net core web api 数据验证(DataAnnotations)

目录 一、什么是 DataAnnotations&#xff1f; 二、扩展验证逻辑&#xff08;自定义验证器&#xff09; 一、什么是 DataAnnotations&#xff1f; DataAnnotations 是一组特性&#xff08;Attributes&#xff09;&#xff0c;用于在模型类上定义验证规则。主要用于属性级别的…

小白从0学习网站搭建的关键事项和避坑指南

以下是针对小白从零学习网站搭建时需要注意的关键事项和避坑指南&#xff0c;帮助你高效学习、少走弯路&#xff1a; 一、学习路径注意事项 不要跳过基础 误区&#xff1a;直接学习框架&#xff08;如 React、Laravel&#xff09;而忽视 HTML/CSS/JS 基础。 正确做法&#xff…

深入剖析JavaScript内存泄漏:识别、定位与实战解决

在JavaScript的世界里&#xff0c;开发者通常不必像使用C那样手动管理内存的分配和释放&#xff0c;这得益于JavaScript引擎内置的垃圾回收&#xff08;Garbage Collection, GC&#xff09;机制。然而&#xff0c;这并不意味着我们可以完全忽视内存管理。“自动"不等于&qu…

2025-04-19 Python 强类型编程

文章目录 1 方法标注1.1 参数与返回值1.2 变参类型1.3 函数类型 2 数据类型2.1 内置类型2.2 复杂数据结构2.3 类别选择2.4 泛型 3 标注方式3.1 注释标注3.2 文件标注 4 特殊情形4.1 前置引用4.2 函数标注扩展4.3 协变与逆变4.4 dataclass 5 高级内容5.1 接口5.2 泛型的协变/逆变…

ETF价格相关性计算算法深度分析

1. 引言 在金融市场中&#xff0c;相关性就像是资产之间“跳舞”的默契程度。想象一下两位舞者&#xff08;ETF&#xff09;&#xff0c;有时步伐一致&#xff0c;有时各跳各的。对于管理大规模资金的投资组合而言&#xff0c;准确理解ETF之间的“舞步同步性”对于风险管理、资…

上海人工智能实验室:LLM无监督自训练

&#x1f4d6;标题&#xff1a;Genius: A Generalizable and Purely Unsupervised Self-Training Framework For Advanced Reasoning &#x1f310;来源&#xff1a;arXiv, 2504.08672 &#x1f31f;摘要 &#x1f538;推进LLM推理技能引起了广泛的兴趣。然而&#xff0c;当前…