初识状态压缩DP

news/2025/1/5 17:19:41/文章来源:https://www.cnblogs.com/califeee/p/18650082

状态压缩DP

通过将状态压缩为整数来达到优化转移的目的。 ——OI Wiki

题目状态 ----> 二进制(01串) ----> 每个二进制对应一个数值 ----> 数值代表着DP状态

例题

摸鱼

题目描述(此题并不是状压DP,是用来理解状态压缩的)

蜗蜗一共有 n\((2 ≤ n ≤ 20)\)天假期,在假期的第 i 天摸鱼他会得到 \(a_i\);\((1≤a_i≤100000)\)的快乐值。
如果蜗蜗每天都摸鱼的话,他会有愧疚感,所以蜗蜗制定了这么个计划:对于每一天,蜗蜗都有一
个列表,如果蜗蜗在列表中的每一天都在摸鱼的话,这一天蜗蜗就不能摸鱼。现在请问蜗蜗如何摸
鱼,使得他能获得的快乐值总和最大?请求出快乐值总和最大是多少。

输入

4			// 4天假期
1 2 3 4		// 每天摸鱼的快乐值
0			// 第i天的计划里有0天
1 1			// 第i+1天的计划里有1天,这天是第一天
1 2
2 2 3

输出

8

思路(状态压缩+暴力)

直接暴力做

假设有 n 天假期,则 n 天的摸鱼情况可以用 n 位的二进制表示,所以情况就是从 [0 .... 0] -> [1....1],0 表示没有摸鱼,1 表示这天摸鱼了。

除了假期,每一天的计划也可以用二进制表示,如何判断一个状态 i 是否可行?如果 i 在 j 天摸鱼了,就去看 j 天的计划,如果

\((i\&s[j] = s[j])\)​ 则不行。

代码

#include <bits/stdc++.h>typedef std::pair<int, int> pii;
#define INF 0x3f3f3f3f
#define MOD 998244353
using i64 = long long;
const int N = 1e5+5;void solve(){int n, ans = 0;std::cin >> n;std::vector<int> v(n+1), b(n+1), l(n+1), s(n+1);for (int i = 1; i <= n; i++) std::cin >> v[i];for (int i = 1; i <= n; i++){std::cin >> l[i];for (int j = 1; j <= l[i]; j++){int x;std::cin >> x;s[i] |= (1 << (x - 1));}}for (int i = 0; i < (1 << n); i++){for (int j = 1, k = i; j <= n; j++, k /= 2){b[j] = k & 1;}bool ok = true;for (int j = 1; j <= n && ok; j++){if (b[j] && l[j] && (i & s[j]) == s[j]){ok = false;}}if (!ok) continue;int res = 0;for (int j = 1; j <= n; j++){if (b[j]){res += v[j];}}ans = std::max(ans, res);}std::cout << ans << '\n';
}signed main()
{std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2);int t = 1, i;for (i = 0; i < t; i++){solve();}return 0;
}

P10447 最短 Hamilton 路径

https://www.luogu.com.cn/problem/P10447

思路

根据题意,假设一共 n 个城市,则哪些城市去了,哪些城市没去很明显可以用二进制表示。

状态定义:\(f[i][j]\):表示在 i 这个状态下,当前在 j 城市的最小花费

初始化:\(f[1][0] = 0\),解释:第一个参数表示 0 这个城市去了,其他城市都没去,且当前在 0 城市,所以自然还没有产生花费

答案:\(f[(1<<n)-1][n-1]\),解释:所以城市都去了的状态是\((1<<n)-1\),当前在 n-1 这座城市

状态转移:\(f[i][j] = \min(f[i][j], f[1\wedge(1<<j)][k]+a[k][j])\),解释:j 城市去过,并且当前在 j 城市的DP值,一定是从 j 城市没有去过,现在刚好可以到达 j 城市的DP值中转移过来的(当前去的每一个城市都可以一步到达 j 城市)

这个转移办法是:思考目前的DP值是怎么来的

代码

#include <bits/stdc++.h>typedef std::pair<int, int> pii;
#define INF 0x3f3f3f3f
#define MOD 998244353
using i64 = long long;
const int N = 1e5+5;void solve(){int n; std::cin >> n;std::vector a(n, std::vector<int>(n, 0));for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){std::cin >> a[i][j];}}std::vector f(1 << 20, std::vector<i64>(n, INT_MAX));f[1][0] = 0;for (int i = 1; i < (1 << n); i++){for (int j = 0; j < n; j++){if (i >> j & 1){for (int k = 0; k < n; k++) if ((i^1 << j) >> k & 1){f[i][j] = std::min(f[i][j], f[i^1<<j][k]+a[k][j]);}}}}std::cout << f[(1<<n)-1][n-1];}signed main()
{std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2);int t = 1, i;for (i = 0; i < t; i++){solve();}return 0;
}

思路二

除了状态转移不一样之外,其他都是一样的

状态转移:\(f[i+(1<<k)][k] = \min(f[i+(1<<k)][k], f[i][j] + a[j][k])\),解释:如果\(f[i][j]\)这个DP值是有意义的,则它一定可以转移到它没有到过的城市

转移方法:根据已经有的DP值转移出新的DP值

代码二

#include <bits/stdc++.h>typedef std::pair<int, int> pii;
#define INF 0x3f3f3f3f
#define MOD 998244353
using i64 = long long;
const int N = 1e5+5;void solve(){int n; std::cin >> n;std::vector a(n, std::vector<int>(n, 0));for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){std::cin >> a[i][j];}}std::vector f(1 << 20, std::vector<i64>(n, INT_MAX));for (int i = 0; i < n; i++){f[0][i] = 0;}f[1][0] = 0;for (int i = 1; i < (1 << n); i++){for (int j = 0; j < n; j++){if (f[i][j] < INT_MAX){for (int k = 0; k < n; k++){if (!(i & (1 << k))){f[i+(1 << k)][k] = std::min(f[i+(1 << k)][k], f[i][j] + a[j][k]);}}}}}std::cout << f[(1<<n)-1][n-1];}signed main()
{std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2);int t = 1, i;for (i = 0; i < t; i++){solve();}return 0;
}

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

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

相关文章

数字化办公的背后:国央企如何为产品提供强大支持

在当今信息化时代,企业的数字化转型正在加速推进。在企业选择软件工具时,安全性、稳定性和合规性是至关重要的因素。尤其是对于企业级应用,这些因素决定了产品的长期可用性和整体价值。而在选择这些工具时,有着国企、央企背景的产品往往能够提供更多的信任和保障。为何有国…

.NET Core + Kafka 开发指南

什么是Kafka Apache Kafka是一个分布式流处理平台,由LinkedIn开发并开源,后来成为Apache软件基金会的顶级项目。Kafka主要用于构建实时数据管道和流式应用程序。Kafka 架构 从下面3张架构图中可以看出Kafka Server 实际扮演的是Broker的角色, 一个Kafka Cluster由多个Broker…

从研究生到管培生,看98年校招生如何让更多企业用上通义灵码

黄天翔是2024年7月入职阿里云的应届校招生,他说,在研究生阶段便已接触并使用通义灵码,通义灵码速度快、学习成本低,几乎无门槛,且具备强大的跨文件理解能力,能生成满足需求的代码。通过实际操作,他利用通义灵码成功构建了一个基于 Python 和 Flask 框架的简易识图网站,…

vscode+vim配置小记

引入 在windows系统下使用vscode+vim编写代码时会遇到一个令人略有不爽的小麻烦。 在vim的normal模式下,首先需要进入insert模式才能正常编写。这里一般是在英文输入法键入相应字母才能进入,比如“i”和“o” 我们进入insert模式之后,在敲代码的过程中难免会需要增加些中文注…

为客户制定个性化健身,我选择用看板软件

借助看板软件可以为客户定制更加个性化的健身计划,提高训练效果和客户满意度。同时,看板软件还能够帮助教练更好地管理训练计划和客户关系,提升工作效率和服务质量。健身机构为客户定制个性化健身计划时,借助看板软件可以极大地提升效率和效果。以下是一个详细的步骤指南,…

有没有一款好用的Win桌面日程安排软件?

之前做了一个小调研,问周围的同事,你觉得一款好用的电脑日程软件应该具有哪些功能? 大多数的同事都回答了以下几个功能:列清单、设提醒、标记完成、日历月视图、可多端同步使用。 我又问,你有好用的日程安排软件推荐吗?大家都表示没有找到特别合适的日程APP。经过一番调研…

【Spring Cloud】8.Spring Cloud Alibaba Nacos——服务注册和配置中心

之前,我已经学习过Nacos的下载和启动。 Nacos 介绍 官网说明:https://nacos.io/docs/latest/quickstart/quick-start/ github地址:https://github.com/alibaba/nacos Nacos: Dynamic Naming And Configuration Service , 动态命名和配置服务 。一个更易于构建云原生应用的动…

中考英语优秀范文-006 How to get on well with others 如何与他人相处融洽

中考英语优秀范文-006 How to get on well with others 如何与他人相处融洽 1 写作要求 当今社会,与人交往越来越成为一种不可或缺的能力,作为中学生,学会如何与人相处尤为重要。假如上周你们班对 “如何与人相处” 展开了讨论,请根据以下的讨论结果,以 “How to get on …

SI24R2 超低功耗高性能 2.4GHz GFSK 无线发射芯片SI24R2重磅出击

SI24R2是一颗工作在2.4GHz ISM频段,专为低功耗无线场合设计,集成嵌入式发射基带的无线发射芯片。工作频率范围为2400MHz-2525MHz,共有126个1MHz带宽的信道。 SI24R2采用GFSK/FSK数字调制与解调技术。数据传输速率与PA输出功率都可以调节,支持2Mbps,1Mbps,250Kbps 三种数据…

揭秘如何用Monaco Editor打造功能强大的日志查看器

Monaco Editor 是一个基于浏览器的代码编辑器,由 Microsoft 开发,是 Visual Studio Code 的核心编辑器组件。为用户提供了一个功能丰富、性能优异的代码编辑环境,常用于 web 应用。 下面本文将从 Monaco Editor 的使用方法、使用逻辑作为切入点,讲述在网页中如何通过 Monac…

【新兴产业】人形机器人

产业链 人形机器人产业链上游为原材料、零部件以及软件平台,核心零部件包括伺服系统、执行器、减速器、控制系统、驱动器等,成本占比最高、技术难度大,具备较高的壁垒。 产业链中游为人形机器人的本体设计、制造及系统集成。 产业链下游为场景应用,目前较有潜力的人形机器人…

PVE 备份快照

PVE 备份快照 - 知乎 抄一个备份 vmware压缩整个虚拟机文件夹就可以连带快照一起打包。 PVE 自带的vzdump备份并不包含快照信息,备份之后再还原,会丢失快照信息。 备份时提示:snapshots found (not included into backup) 快照信息在循序渐进的开发模式中十分重要,遇到错误…