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

店面门头在线设计网站做设计有哪些地图网站

店面门头在线设计网站,做设计有哪些地图网站,万江仿做网站,软装设计网站大全在蓝桥杯中遇到的这道题,看上去比较普通,但其实蕴含了很巧妙的“状态压缩 背包”的思想,本文将从零到一,详细解析这个问题。 目录 一、题目 二、思路分析:状态压缩 最小覆盖 1. 本质:最小集合覆盖问题…

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

目录

一、题目 

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

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 存储,否则可能溢出

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

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

http://www.dtcms.com/wzjs/596513.html

相关文章:

  • 盐城手机网站建设公司做网站设计用到的软件
  • 开发网站中心网站建设和整改方案
  • 做网站颜色如何搭配网站备案做优惠券
  • 做网站能给公司带来什么好处网站开发实战演练
  • 网站建设与管理试卷及答案网站建设开源节流
  • 电商网站建设毕业设计小程序开发教程百度网盘
  • 为什么网站建设起来搜素不到建筑工人网上找活
  • 旅游网站策划书app购物网站建设
  • 吉林省 网站建设建网站商城
  • 做视频投稿赚钱的网站服装公司网站网页设计
  • 宜昌网站网站建设免费建设音乐网站
  • 百度权重高的网站有哪些个人怎么做网络推广
  • 上海网站制作团队网站开发人员属于什么
  • 网站建设与管理专业教学标准公司没注册可以做网站吗
  • 福州外贸网站建设推广微商营销软件商城
  • 潍坊建设网站的公司网站建设一般要多少费用
  • 济南建设网站公司建立网站公司有哪些
  • 动态设计参考网站wordpress 页面查询
  • 兴仁市建设局网站潍坊免费模板建站
  • 企业网站可信度建设长春建站的费用
  • 企业在阿里做网站是什么意思电商网站对比
  • 绍兴做网站哪家好博客网站模板有哪些
  • 初创品牌网站建设好男人社区
  • wordpress 提示插件贵州网站优化
  • 南海区住房城乡建设和水务局网站优化设计答案六年级
  • 金昌网站建设专门做spa的网站
  • wordpress下载资源站主题深圳网络营销推广外包
  • 哪里做网站需求南京汽车企业网站建设
  • 漳州做网站喊多少钱phpcms资讯类网站模板
  • 网站推广指的是什么自媒体素材视频网站