当前位置: 首页 > article >正文

【算法竞赛】状态压缩型背包问题经典应用(蓝桥杯2019A4分糖果)

在蓝桥杯中遇到的这道题,看上去比较普通,但其实蕴含了很巧妙的“状态压缩 + 背包”的思想,本文将从零到一,详细解析这个问题。

目录

一、题目 

二、思路分析:状态压缩 + 最小覆盖

1. 本质:最小集合覆盖问题

2. 状态设计:压缩子集状态

3. 状态转移逻辑

4. 为什么不用回溯解决?

三、状压DP通用压缩和转移技巧

1. 应用场景

2. 状压DP的核心构建思维

3. 状态遍历技巧

四、代码

五、关键点总结


一、题目 

4.糖果 - 蓝桥云课

 【翻译过来就是】:

店里有 M 种不同口味的糖果。老板不单卖糖果,而是将 K 颗糖果打包成一包,并且每包糖果的口味可以预知。小明希望通过购买若干包糖果,品尝到所有 M 种口味

我们的目标是:求出小明最少要买多少包糖果,才能尝到所有口味?
若无论如何都无法凑齐所有口味,输出 -1

二、思路分析:状态压缩 + 最小覆盖

1. 本质:最小集合覆盖问题

这道题本质上是一个最小集合覆盖问题

给定 M 个元素的全集,每个集合(糖果包)覆盖部分元素,求用最少的集合数量,使得它们的并集恰好覆盖全集。

这类问题是组合优化中非常典型的 NP 完全问题,而这道题因为数据规模小(M ≤ 20),我们可以用状态压缩优化搜索空间

2. 状态设计:压缩子集状态

考虑全集是口味 {1, 2, ..., M},那么每种“已经吃到的口味组合”可以表示为一个二进制串,长度为 M

  • i 位为 1 表示第 i 种口味已吃;

  • i 位为 0 表示第 i 种口味未吃;

  • 例如 01101 表示尝到了第 0、2、3 种口味。

于是我们就可以设计出如下的状态压缩动态规划:

  • 状态定义dp[s] 表示要想吃到状态 s 表示的口味集合,最少要买多少包糖果;

  • 状态个数:全集口味数为 M,所以一共有 2^M 个状态

  • 初始状态dp[0] = 0 表示什么都没吃;

  • 最终目标:我们要找出 dp[full],其中 full=(1<<M)-1,即全1,代表吃全所有口味

3. 状态转移逻辑

我们遍历每一包糖果(相当于“可以选的物品”),如果当前状态是 j,那么加入这一包糖果之后,会变成新状态 j|a[i]

转移公式如下:

dp[j|a[i]] = min(dp[j|a[i]], dp[j]+ 1)

意思是:“如果我当前吃到的是状态j,现在加上这包糖果 a[i],我就能达到一个新的状态j |a[i],那到达新状态的最小糖果包数,可能是之前状态的基础上+1

为了避免状态转移时污染原始状态(避免用新的 dp[j|a[i]]去影响其它转移),我们从大到小遍历状态 j

4. 为什么不用回溯解决?

很多读者第一时间可能想到回溯 + 剪枝,但那样复杂度是指数级的

这题可以用动态规划,是因为

  • 状态可以表示为一个整数,并且状态间的转移有明显结构

  • 每一步的选择(糖果包)都可以使得状态“合并”;

  • 我们可以用子问题的最优解构造出大问题的最优解,符合DP的子结构性质。

三、状压DP通用压缩和转移技巧

状态压缩 DP是竞赛算法中经常考的一种技巧,尤其当状态具有“组合”性质时非常常见

1. 应用场景

  • 集合覆盖类问题(如本题)

  • 旅行商问题(TSP)

  • 开关灯问题 / 翻牌问题

  • 博弈论中已访问节点记录

  • 图上路径问题中“走过哪些点”状态的保存

2. 状压DP的核心构建思维

  1. 状态压缩

    • 使用一个整数的二进制表示“某种集合”

    • 长度为 M 的集合有 2^M 个子集,对应 0~2^M - 12^M 个整数

  2. 状态定义

    • 每一个状态代表一种“中间形态”,可以是路径、集合、排列的某种子结构

    • dp[mask] 表示从起点出发,达到状态 mask 所需要的最小代价/方案数等

  3. 状态转移

    • 通常通过 dp[old_mask]->dp[new_mask] 来实现

    • new_mask=old_mask|(1<<x) 表示在old_mask 的基础上加入一个新元素

    • 利用位运算快速合并和判断状态(如:是否包含、是否重叠等)

3. 状态遍历技巧

接下来给大家附上一下状态压缩常用的小技巧

遍历目标写法
遍历所有状态for (int mask = 0; mask < (1 << M); mask++)
遍历 mask 的所有子集for (int sub = mask; sub; sub = (sub - 1) & mask)
检查 mask 是否包含第 iif (mask & (1 << i))
加入元素 imask | (1 << i)
删除元素 imask & ~(1 << i)

四、代码

#include <iostream>
#include <cstring>
#include <algorithm> 
#include <climits>
using namespace std;
long long dp[(1<<20)+1];//左移20位
int n,m,k;
int a[110];//第i包所有的种类 
int main()
{fill(dp,dp+(1<<20)+1,INT_MAX);//初始化为最大值cin>>n>>m>>k;//n包糖果,m种口味,每包k种int c[25];//占位数组,是否能全部尝到fill(c,c+m,0);bool no=false;//是否能全部尝到//读入n包糖果for(int i=1;i<=n;i++){int x=0,y;for(int j=1;j<=k;j++){cin>>y;//转换为二进制//(1后面有y-1个0,相当于第y位是1) y--;x|=(1<<y); //先检验糖果是否全 //索引向后移一位 c[y]++;}a[i]=x;} //首先检验糖果种类是否齐全for(int i=0;i<m;i++){if(!c[i]) no=true;} if(no) cout<<"-1";else{//背包问题,装i包糖果使每一种口味都能尝到 dp[0]=0;//遍历每一包 for(int i=1;i<=n;i++){//状态从大到小 //背包问题,滚动数组背包容量从大到小 for(int j=(1<<m)-1;j>=0;j--){//是否选第i包 dp[j|a[i]]=min(dp[j|a[i]],dp[j]+1);}}//0-m-1位都为1 cout<<dp[(1<<m)-1];}return 0;
} 

五、关键点总结

技巧说明
状态压缩将口味组合转换为一个整数表示
背包状态转移dp[new_state] = min(dp[new_state], dp[old_state] + 1)
滚动数组优化状态转移从大到小,避免重复选择
初始化技巧INT_MAX 代表当前状态不可达,一定要用 long long 存储,否则可能溢出

这个问题很好的考察了对“状态压缩 + 背包模型”的掌握,也是一道蓝桥杯常考的“最小覆盖子集”变形题,可以作为一道练手题

如果你觉得本文对你有帮助,欢迎点赞收藏!

相关文章:

【算法竞赛】状态压缩型背包问题经典应用(蓝桥杯2019A4分糖果)

在蓝桥杯中遇到的这道题&#xff0c;看上去比较普通&#xff0c;但其实蕴含了很巧妙的“状态压缩 背包”的思想&#xff0c;本文将从零到一&#xff0c;详细解析这个问题。 目录 一、题目 二、思路分析&#xff1a;状态压缩 最小覆盖 1. 本质&#xff1a;最小集合覆盖问题…...

kali——masscan

目录 前言 使用方法 前言 Masscan 是一款快速的端口扫描工具&#xff0c;在 Kali Linux 系统中常被用于网络安全评估和渗透测试。 使用方法 对单个IP进行端口扫描&#xff1a; masscan -p11-65535 192.168.238.131 扫描指定端口&#xff1a; masscan -p80,22 192.168.238.131…...

常微分方程 1

slow down and take your time 定积分应用回顾常微分方程的概述一阶微分方程可分离变量齐次方程三阶线性微分方程 一阶线性微分方程不定积分的被积分函数出现了绝对值梳理微分方程的基本概念题型 1 分离变量题型 2 齐次方程5.4 题型 3 一阶线性微分方程知识点5.55.6 尾声 定积分…...

Web前端页面搭建

1.在D盘中创建www文件 cmd进入窗口命令windowsR 切换盘符d: 进入创建的文件夹 在文件夹里安装tp框架 在PS中打开tp文件 创建网站&#xff0c;根目录到public 在浏览器中打开网页 修改文件目录名称 在public目录中的。htaccess中填写下面代码 <IfModule mod_rewrite.c >…...

开源 LLM 应用开发平台 Dify 全栈部署指南(Docker Compose 方案)

开源 LLM 应用开发平台 Dify 全栈部署指南&#xff08;Docker Compose 方案&#xff09; 一、部署环境要求与前置检查 1.1 硬件最低配置 组件要求CPU双核及以上内存4GB 及以上磁盘空间20GB 可用空间 1.2 系统兼容性验证 ✅ 官方支持系统&#xff1a; Ubuntu 20.04/22.04 L…...

BN 层的作用, 为什么有这个作用?

BN 层&#xff08;Batch Normalization&#xff09;——这是深度神经网络中非常重要的一环&#xff0c;它大大改善了网络的训练速度、稳定性和收敛效果。 &#x1f9e0; 一句话理解 BN 层的作用&#xff1a; Batch Normalization&#xff08;批归一化&#xff09;通过标准化每一…...

JavaScript 中常见的鼠标事件及应用

JavaScript 中常见的鼠标事件及应用 在 JavaScript 中&#xff0c;鼠标事件是用户与网页进行交互的重要方式&#xff0c;通过监听这些事件&#xff0c;开发者可以实现各种交互效果&#xff0c;如点击、悬停、拖动等。 在 JavaScript 中&#xff0c;鼠标事件类型多样&#xff0…...

【nginx】Nginx的功能特性及常用功能

目录 1.核心功能特性1.1 高并发处理能力1.2 反向代理与负载均衡1.3 静态资源服务1.4 缓存加速1.5 SSL/TLS支持1.6 动态模块扩展1.7 流媒体服务1.8 高可用性 2.常用功能场景2.1 反向代理与负载均衡2.2 静态资源服务2.3 缓存加速2.4 HTTPS支持2.5 API网关2.6 微服务网关 3.优势总…...

make_01_Program_01_makefile .SECONDARY .dirstamp 是什么功能

在 Makefile 中&#xff0c;.SECONDARY 和 .dirstamp 与 GNU Make 处理文件和目标的方式有关。让我们分别解释这两个部分&#xff0c;以及它们结合在一起时的功能。 .SECONDARY 功能&#xff1a;.SECONDARY 是一个特殊的伪目标&#xff0c;用于告诉 make 保留所有中间目标文件…...

金仓数据库KCM认证考试介绍【2025年4月更新】

KCM&#xff08;金仓认证大师&#xff09;认证是金仓KES数据库的顶级认证&#xff0c;学员需通过前置KCA、KCP认证才能考KCM认证。 KCM培训考试一般1-2个月一次&#xff0c;KCM报名费原价为1.8万&#xff0c;当前优惠价格是1万&#xff08;趋势是&#xff1a;费用越来越高&…...

在 macOS 上安装和配置 Aria2 的详细步骤

在 macOS 上安装和配置 Aria2 的详细步骤&#xff1a; 1.安装 Aria2 方式一&#xff1a;使用 Homebrew Homebrew 是 macOS 上的包管理器&#xff0c;可以方便地安装和管理软件包。 • 打开终端。 • 输入以下命令安装 Aria2&#xff1a; brew install aria2• 检查安装是否…...

如何通过句块训练法(Chunks)提升英语口语

真正说一口流利英语的人&#xff0c;并不是会造句的人&#xff0c;而是擅长“调取句块”的人。下面我们从原理、方法、场景、资源几个维度展开&#xff0c;告诉你怎么用“句块训练法&#xff08;Chunks&#xff09;”快速提升英语口语&#xff1a; 一、什么是“句块”&#xff…...

[ctfshow web入门]burpsuite的下载与使用

下载 吾爱破解网站工具区下载burpsuite https://www.52pojie.cn/thread-1544866-1-1.html 本博客仅转载下载链接&#xff0c;下载后请按照说明进行学习使用 打开 配置 burpsuite配置 burpsuite代理设置添加127.0.0.1:8080 浏览器配置 如果是谷歌浏览器&#xff0c;打开win…...

文章记单词 | 第25篇(六级)

一&#xff0c;单词释义 mathematical&#xff1a;形容词&#xff0c;意为 “数学的&#xff1b;数学上的&#xff1b;运算能力强的&#xff1b;关于数学的”trigger&#xff1a;名词&#xff0c;意为 “&#xff08;枪的&#xff09;扳机&#xff1b;&#xff08;炸弹的&…...

vscode集成deepseek实现辅助编程(银河麒麟系统)【详细自用版】

针对开发者用户&#xff0c;可在Visual Studio Code中接入DeepSeek&#xff0c;实现辅助编程。 可参考我往期文章在银河麒麟系统环境下部署DeepSeek&#xff1a;基于银河麒麟桌面&&服务器操作系统的 DeepSeek本地化部署方法【详细自用版】 一、前期准备 &#xff08…...

【CMake】《CMake构建实战:项目开发卷》笔记-Chapter8-生成器表达式

第8章 生成器表达式 生成器表达式&#xff08;generator expression&#xff09;是由CMake生成器进行解析的表达式&#xff0c;因此&#xff0c;这些表达式只有在CMake的生成阶段才被解析为具体的值。 CMake在生成阶段&#xff0c;能够根据具体选用的构建系统生成器生成特定…...

elementui的默认样式修改

今天用element ui &#xff0c;做了个消息提示&#xff0c;发现提示的位置总是在上面&#xff0c;如图&#xff1a; 可是我想让提示的位置到下面来&#xff0c;该怎么办&#xff1f; 最后还是看了官方的api 原来有个自定义样式属性 customClass 设置下就好了 js代码 css代码 效…...

基于STM32的智能门禁系统设计与实现

一、项目背景与功能概述 在物联网技术快速发展的今天&#xff0c;传统门锁正在向智能化方向演进。本系统基于STM32F103C8T6微控制器&#xff0c;整合多种外设模块&#xff0c;实现了一个具备以下核心功能的智能门禁系统&#xff1a; 密码输入与验证&#xff08;4x3矩阵键盘&a…...

基于SpringBoot的河道水情大数据可视化分析平台设计与实现(源码+论文+部署讲解等)

需要资料&#xff0c;请文末联系 一、平台介绍 水情监测数据大屏 - 平台首页 日均水位 日均水速 二、论文内容 摘要&#xff08;中文&#xff09; 本文针对河道水情监测领域的数据管理和可视化分析需求&#xff0c;设计并实现了一套河道水情大数据可视化分析平台。该平台基…...

日志统计(双指针)

题目描述 小明维护着一个程序员论坛。现在他收集了一份"点赞"日志&#xff0c;日志共有 NN 行。其中每一行的格式是&#xff1a; ts idts id 表示在 tsts 时刻编号 idid 的帖子收到一个"赞"。 现在小明想统计有哪些帖子曾经是"热帖"。如果一个帖…...

广告推荐算法:COSMO算法与A9算法的对比

COSMO算法与A9算法的概念解析 1. A9算法 定义与背景&#xff1a; A9算法是亚马逊早期为电商平台研发的核心搜索算法&#xff0c;主要用于优化商品搜索结果的排序和推荐&#xff0c;其核心逻辑围绕产品属性与关键词匹配展开。自2003年推出以来&#xff0c;A9通过分析商品标题…...

Java进阶之旅-day05:网络编程

引言 在当今数字化的时代&#xff0c;网络编程在软件开发中扮演着至关重要的角色。Java 作为一门广泛应用的编程语言&#xff0c;提供了强大的网络编程能力。今天&#xff0c;我们深入学习了 Java 网络编程的基础知识&#xff0c;包括基本的通信架构、网络编程三要素、IP 地址、…...

Vue 3 的响应式原理

Vue 3 的响应式原理可以比喻为“智能监控系统”&#xff1a;当数据变化时&#xff0c;它能自动追踪依赖关系并触发更新。以下是通俗解释和核心机制&#xff1a; 一、核心原理&#xff1a;Proxy 代理 Vue 3 的响应式系统基于 JavaScript 的 Proxy 对象实现&#xff08;Vue 2 使…...

Python解决“组成字符串ku的最大次数”问题

Python解决“组成字符串ku的最大次数”问题 问题描述测试样例解题思路代码 问题描述 给定一个字符串 s&#xff0c;该字符串中只包含英文大小写字母。你需要计算从字符串中最多能组成多少个字符串 “ku”。每次可以随机从字符串中选一个字符&#xff0c;并且选中的字符不能再使…...

【JS】使用滑动窗口得到无重复字符的最长子串

题目 思路 本题采用滑动窗口思想&#xff0c;定义左右指针作为滑动窗口的边界&#xff0c;使用Set数据结构处理重复字符&#xff0c;需要注意的是&#xff1a;每次遍历时采用Math.max方法实时更新最长子串的长度&#xff1b;当左指针移动时&#xff0c;set要删除对应字符。 步…...

libreoffice-help-common` 的版本(`24.8.5`)与官方源要求的版本(`24.2.7`)不一致

出现此错误的原因主要是软件包依赖冲突&#xff0c;具体分析如下&#xff1a; ### 主要原因 1. **软件源版本不匹配&#xff08;国内和官方服务器版本有差距&#xff09; 系统中可能启用了第三方软件源&#xff08;如 PPA 或 backports 源&#xff09;&#xff0c;导致 lib…...

2025-04-05 吴恩达机器学习4——逻辑回归(1):基础入门

文章目录 1 分类问题1.1 介绍1.2 线性回归与分类1.2 逻辑回归 2 逻辑回归2.1 介绍2.2 Sigmoid 函数2.3 逻辑回归模型 3 决策边界3.1 概念3.2 线性决策边界3.3 非线性决策边界 4 代价函数4.1 不使用平方误差4.2 损失函数4.3 整体代价函数 5 梯度下降5.1 参数更新5.2 逻辑回归 vs…...

P1125 [NOIP 2008 提高组] 笨小猴

#include<bits/stdc.h> using namespace std; int a[300],ma,mi105;//数组用来记录每个字符出现的次数&#xff0c;将mi初始为一个比较大的值 bool is_prime(int x){if(x0||x1)return false;for(int i2;i*i<x;i){if(x%i0)return false;}return true; }//判断是否为质…...

Linux systemd 服务全面详解

一、systemd 是什么&#xff1f; systemd 是 Linux 系统的现代初始化系统&#xff08;init&#xff09;和服务管理器&#xff0c;替代传统的 SysVinit 和 Upstart。它不仅是系统启动的“总指挥”&#xff0c;还统一管理服务、日志、设备挂载、定时任务等。 核心作用 服务管理…...

SortedSet结构之用户积分实时榜单实战

Redis 中的SortedSet结构非常适合用于实现实时榜单的场景&#xff0c;它根据成员的分数自动进行排序&#xff0c;支持高效的添加、更新和查询操作。 SortedSet实时榜单的一些典型应用场景&#xff1a; 游戏中的玩家排行榜&#xff1a;在多人在线游戏中&#xff0c;使用 Sorte…...