【洛谷 P8687】[蓝桥杯 2019 省 A] 糖果 题解(动态规划+位集合+位运算)

news/2025/2/10 23:05:22/

[蓝桥杯 2019 省 A] 糖果

题目描述

糖果店的老板一共有 M M M 种口味的糖果出售。为了方便描述,我们将 M M M 种口味编号 1 1 1 M M M

小明希望能品尝到所有口味的糖果。遗憾的是老板并不单独出售糖果,而是 K K K 颗一包整包出售。

幸好糖果包装上注明了其中 K K K 颗糖果的口味,所以小明可以在买之前就知道每包内的糖果口味。

给定 N N N 包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖果。

输入格式

第一行包含三个整数 N N N M M M K K K

接下来 N N N 行每行 K K K 这整数 T 1 , T 2 , ⋯ , T K T_1,T_2, \cdots ,T_K T1,T2,,TK,代表一包糖果的口味。

输出格式

一个整数表示答案。如果小明无法品尝所有口味,输出 − 1 -1 1

样例 #1

样例输入 #1

6 5 3
1 1 2
1 2 3
1 1 3
2 3 5
5 4 2
5 1 2

样例输出 #1

2

提示

对于 30 % 30\% 30% 的评测用例, 1 ≤ N ≤ 20 1 \le N \le 20 1N20

对于所有评测样例, 1 ≤ N ≤ 100 1 \le N \le 100 1N100 1 ≤ M ≤ 20 1 \le M \le 20 1M20 1 ≤ K ≤ 20 1 \le K \le 20 1K20 1 ≤ T i ≤ M 1 \le T_i \le M 1TiM

蓝桥杯 2019 年省赛 A 组 I 题。


思路

首先,定义一个数组 candy,数组的每个元素都是一个位集,表示每个糖果包中糖果的口味。然后,定义一个数组 dp,数组的每个元素表示对应的口味状态下最少需要购买的糖果包的数量。初始化 dp 数组的所有元素为 INF,表示无法达到对应的口味状态。

接着,从输入中读取糖果包的数量 n,糖果的口味数量 m,每个糖果包中糖果的数量 k。对于每个糖果包,从输入中读取 k 个糖果的口味,然后更新 candy 数组的相应元素。

然后,进行动态规划。状态转移方程为:

d p [ i ] = min ⁡ ( d p [ i ] , d p [ j ] + 1 ) dp[i] = \min(dp[i], dp[j] + 1) dp[i]=min(dp[i],dp[j]+1)

其中, j j j 是当前的口味状态, i i i 是通过购买某个糖果包从 j j j 状态转移到的新的口味状态。如果可以通过购买一个糖果包从 j j j 状态转移到 i i i 状态,那么就更新 i i i 状态下最少需要购买的糖果包的数量。

对于每个糖果包和每个口味状态,如果当前的口味状态可以通过购买当前的糖果包来达到,那么就更新 dp 数组的相应元素。具体来说,如果 dp[j] 的值不大于 100,那么就用位运算符 | 来得到新的口味状态 k,然后用 min 函数来更新 dp[k] 的值。

最后,输出 dp 数组中表示所有口味的元素的值。如果这个值等于 INF,那么就输出 -1,表示无法品尝所有口味;否则就输出这个值,表示最少需要购买的糖果包的数量。


AC代码

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstring>
#include <iostream>
#define AUTHOR "HEX9CF"
using namespace std;
using ll = long long;const int N = 1e2 + 7;
const int M = 20;
const ll L = (1 << M);
const int INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;// n包,m种,每包k颗
int n, m, k;
// i状态最少需要的包数
int dp[L];
bitset<M> candy[N];int main() {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);memset(dp, INF, sizeof(dp));cin >> n >> m >> k;for (int i = 0; i < n; i++) {candy[i].reset();for (int j = 0; j < k; j++) {int t;cin >> t;candy[i][t - 1] = 1;}// cout << candy[i] << endl;}dp[0] = 0;for (int i = 0; i < n; i++) {for (int j = 0; j < (1 << m); j++) {bitset<M> t(j);if (dp[j] > 100) {continue;}int k = (t | candy[i]).to_ullong();// cout << k << endl;dp[k] = min(dp[k], dp[j] + 1);}}cout << ((dp[(1 << m) - 1] == INF) ? -1 : dp[(1 << m) - 1]) << endl;return 0;
}

http://www.ppmy.cn/news/1391500.html

相关文章

【C++】1600. 请假时间计算

问题&#xff1a;1600. 请假时间计算 类型&#xff1a;基本运算、整数运算 题目描述&#xff1a; 假设小明的妈妈向公司请了 n 天的假&#xff0c;那么请问小明的妈妈总共请了多少小时的假&#xff0c;多少分钟的假&#xff1f;&#xff08;提示&#xff1a; 1 天有 24 小时&…

HarmonyOS 应用开发案例

本帖下方集中了HarmonyOS Next应用开发时&#xff0c;会遇到的常见应用案例。后续会持续更新大量案例&#xff0c;帮助开发者快速学习。欢迎感兴趣的同学加入Q&#xff1a;454901491 72.手写绘制及保存图片案例&#xff08;0319更新&#xff09;&#xff08;点此查看源码实现&…

【呼市经开区建设服务项目水、电能耗监测 数采案例】

实施方案 针对能耗采集中的水、电能源数据采集&#xff0c;因客观因素条件&#xff0c;数据采集方面存在较大难度。大多数国网电表485接口由于封签限制&#xff0c;不能实施采集&#xff0c;不让拆机接线&#xff0c;采集实施存在困难。水量能耗采集&#xff0c;存在类似问题&a…

Java毕业设计-基于springboot开发的书籍学习平台-毕业论文+答辩PPT(附源代码+演示视频)

文章目录 前言一、毕设成果演示&#xff08;源代码在文末&#xff09;二、毕设摘要展示1、开发说明2、需求分析3、系统功能结构 三、系统实现展示1、平台功能模块2、后台功能模块2.1管理员功能模块2.2用户功能模块2.3作者功能模块 四、毕设内容和源代码获取总结 Java毕业设计-基…

(vue)新闻列表与图片对应显示,体现选中、移入状态

(vue)新闻列表与图片对应显示&#xff0c;体现选中、移入状态 项目背景&#xff1a;郑州院XX项目首页-新闻展示模块&#xff0c;鼠标移入显示对应图片&#xff0c;且体现选中和移入状态 首次加载&#xff1a; 切换列表后&#xff1a; html: <el-row :gutter"20"…

图解 LFU 缓存淘汰算法以及在 Redis 中的应用(附带个人完整代码实现)

文章目录 LFU 算法理论介绍算法实现数据结构查询操作插入/更新操作 Redis 缓存淘汰算法缓存污染难题Redis LFU缓存淘汰策略 本篇博客的主要内容&#xff1a; 以图解的方式&#xff0c;介绍 LFU 算法的一种实现&#xff1b;介绍 LFU 算法在 Redis 中的应用。 LFU 算法 理论介…

Java中最简单的添加日志链路的方式之一

Java项目中添加日志链路功能的设计与实现 文章目录 Java项目中添加日志链路功能的设计与实现前言一、日志链路的概念与作用二、添加日志链路的设计思路三、如何支持多线程下的日志打印也附加上日志链路id1. 示例1&#xff1a;实现Runnable接口&#xff0c;无返回值2. 示例2&…

【ubuntu20.04+tensorflow-gpu1.14配置】

ubuntu20.04tensorflow-gpu1.14配置 目录0. 版本注意事项说明1. 个人目录下载后配置系统环境变量2. anaconda配置所有环境&#xff08;过程简便&#xff0c;但容易出现不兼容问题&#xff09;3. 验证tensorflow-gpu4. 一些细节 目录 总结出两种方法 个人目录 下载cuda和cudnn…