蓝桥杯.糖果(状压dp)

Question:

Solve:

核心:

状态压缩二进制存数

枚举尝试拿糖果

dp得出最后结果

首先考虑数据存放,最直接的肯定是二维数组,bool a[i][j],第i包糖果是否含有第j种糖果

很明显,这样放空间占用大,而且数组遍历浪费时间

因为最大的糖果种数也就20,且每包糖果里每种糖果只有有或者没有两种状态

所以可以使用二进制来存放,比如0101表示含有第一种和第三种糖果,那所谓的拿到所有种类糖果也就是二进制数所有位数都为1,这样存放还有一个什么好处呢,比如我取了两包糖果,一包10100,另一包00101,那我现在所拥有的糖果种类就可以表示为两数按位或 10100 | 00101 = 10101

思考到这里以后再想,怎么保证得到的结果是最小呢,那就只有枚举

在枚举尝试每一包的糖果的时候,我可以去用dp[xxxxxxx] = v来表示拿到xxxxxxx中所含糖果需要拿的最小包数为v, 并通过不断刷新v来得到最后结果(二进制是xxxxxxx,但是dp实际的下标1肯定是要用十进制表示的哈)

想到这一步之后问题也就解决了,结果自然就是dp[(1<<m)-1]了,m种糖果,(1<<m)-1不就是m个数位都是1所表示的十进制数吗?

Code:

#include <bits/stdc++.h>
using namespace std;
int n, m, k, x;
int a[110]; 
int dp[1<<21];
int main(void)
{
    cin >>n >>m >>k;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= k; j++){
            //读入每包糖果 
			cin >>x;
            a[i] |= 1 << (x - 1);
        }
    }
    //dp初始化 
    //因为是不断刷新最小值,所以初始化应该是最大值 
    memset(dp, 127, sizeof(dp));
    dp[0] = 0;
    
    for(int i = 1; i <= n; i++){
        for(int j = 0; j <  (1 << m); j++){
            //如果最小次数已经大于n,跳过 
			if(dp[j] > n) continue;
            //将原来得到糖果所需的次数与当前次数比较并赋值 
			dp[j | a[i]] = min(dp[j | a[i]], dp[j] + 1);
        }
    }
    //如果拿到所有糖果所需次数大于n(其实应该是因为某种糖果没有),输出-1 
    if(dp[(1<<m)-1] > n) cout <<-1;
    else cout <<dp[(1<<m)-1];
    return 0;
}

最后附上蓝桥杯汇总链接:蓝桥杯C/C++A组省赛历年真题题解 

声明:图片均来源于蓝桥杯官网,以个人刷题整理为目的,如若侵权,请联系删除~

  • 18
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
糖果是一道经典的编程题目,常出现在编程竞赛中,比如蓝桥杯。题目描述如下: 给定一个长度为n的数组,表示n个小朋友的评分。现在需要将糖果分给这些小朋友,要求满足以下条件: 1. 每个小朋友至少分到一个糖果。 2. 评分更高的小朋友比他相邻的小朋友分到的糖果数量更多。 要求:计算最少需要多少个糖果才能满足以上条件。 解题思路: 1. 首先初始化一个长度为n的糖果数组,每个元素都为1,表示每个小朋友至少分到一个糖果。 2. 从左到右遍历评分数组,如果当前小朋友的评分比前一个小朋友高,则将当前小朋友的糖果数量设置为前一个小朋友的糖果数量加1。 3. 从右到左再遍历一次评分数组,如果当前小朋友的评分比后一个小朋友高,并且当前小朋友的糖果数量不大于后一个小朋友的糖果数量,则将当前小朋友的糖果数量设置为后一个小朋友的糖果数量加1。 4. 最后将糖果数组中所有元素的值相加,即为最少需要的糖果数量。 下面是分糖果问题的Python代码示例: ```python def minCandies(ratings): n = len(ratings) candies = * n for i in range(1, n): if ratings[i] > ratings[i-1]: candies[i] = candies[i-1] + 1 for i in range(n-2, -1, -1): if ratings[i] > ratings[i+1] and candies[i] <= candies[i+1]: candies[i] = candies[i+1] + 1 return sum(candies) # 测试样例 ratings = [1, 3, 2, 1, 2, 4, 3] result = minCandies(ratings) print(result) # 输出:12 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UmVfX1BvaW50

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值