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

蓝桥杯每日一真题——[蓝桥杯 2021 省 AB] 砝码称重(背包dp)

文章目录

      • 题目详情:
  • [蓝桥杯 2021 省 AB] 砝码称重
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例
      • 样例输入
      • 样例输出
    • 提示
      • 思路:
      • 方法:
      • 全部代码:
      • 注意事项

题目详情:

[蓝桥杯 2021 省 AB] 砝码称重

题目描述

你有一架天平和 N N N 个砝码, 这 N N N 个砝码重量依次是 W 1 , W 2 , ⋯   , W N W_{1}, W_{2}, \cdots, W_{N} W1,W2,,WN 。 请你计算一共可以称出多少种不同的重量?

注意砝码可以放在天平两边。

输入格式

输入的第一行包含一个整数 N N N

第二行包含 N N N 个整数: W 1 , W 2 , W 3 , ⋯   , W N W_{1}, W_{2}, W_{3}, \cdots, W_{N} W1,W2,W3,,WN

输出格式

输出一个整数代表答案。

样例

样例输入

3
1 4 6

样例输出

10

提示

【样例说明】

能称出的 10 种重量是: 1 、 2 、 3 、 4 、 5 、 6 、 7 、 9 、 10 、 11 1 、 2 、 3 、 4 、 5 、 6 、 7 、 9 、 10 、 11 123456791011

1 = 1 2 = 6 − 4 (  天平一边放  6 ,  另一边放 4)  3 = 4 − 1 4 = 4 5 = 6 − 1 6 = 6 7 = 1 + 6 9 = 4 + 6 − 1 10 = 4 + 6 11 = 1 + 4 + 6 \begin{aligned} &1=1 \\ &2=6-4(\text { 天平一边放 } 6, \text { 另一边放 4) } \\ &3=4-1 \\ &4=4 \\ &5=6-1 \\ &6=6 \\ &7=1+6 \\ &9=4+6-1 \\ &10=4+6 \\ &11=1+4+6 \end{aligned} 1=12=64( 天平一边放 6, 另一边放 4) 3=414=45=616=67=1+69=4+6110=4+611=1+4+6

【评测用例规模与约定】

对于 50 % 50 \% 50% 的评测用例, 1 ≤ N ≤ 15 1 \leq N \leq 15 1N15

对于所有评测用例, 1 ≤ N ≤ 100 , N 1 \leq N \leq 100, N 1N100,N 个砝码总重不超过 1 0 5 10^5 105

蓝桥杯 2021 第一轮省赛 A 组 F 题(B 组 G 题)。


思路:

如果把每一个砝码想像成物品的话那么这个物品有增加这个和减少这个两种状态,
那么一共可能放的砝码总重就是这个物品的容量。那这个题就是一个明显的背包问题,如果你还不会背包问题请移步:背包问题

方法:

1.可以循环物品和背包(能放多重的砝码(也就是砝码总和))看当前的砝码能否充满当前的背包容量。能就1,不能就0,最后看把n个物品放进去有多少个背包是充满的。

2·dp[][]数组的定义,这个问题是让我们求能有多少中放法,有两种状态,一个是当前将第几个物品放入,一个是当前物品的重量是否能充满当前的背包;这样的话我们可以让dp[放入第i个物品][当前物品的重量]=当前物品的重量是否能充满当前的背包;

3.分为四种状态

  1. 不放砝码,上一次物品怎样我就怎样能成就成不能成就散。 dp[i][j] = dp[i - 1][j];
  2. 天平上只有当前的砝码 if (w[i] == j) dp[i][j] = 1;
  3. 加上当前砝码重量else if (dp[i - 1][j + w[i]] == 1) dp[i][j] = 1;
  4. 减去当前砝码重量 else if (dp[i - 1][abs(j - w[i])] == 1) dp[i][j] = 1;

4·统计。(自己统计去)

5·当然这个也可以压缩成滚动数组的形式不过这样的比较好理解

全部代码:

#include <iostream>
using namespace std;
int n, w[101], smax, ans;
bool dp[101][100001];
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> w[i];
        smax = smax + w[i]; // 把所有砝码都加起来就是最大值
    }
    dp[0][0] = 1;
    // 双重循环,遍历dp。
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= smax; j++)
        {
           
            dp[i][j] = dp[i - 1][j]; // 不放砝码,沿用上一个的状态
            if (w[i] == j)
                dp[i][j] = 1; // 只放现在的那个砝码。
            else if (dp[i - 1][j + w[i]] == 1)
                dp[i][j] = 1;//加上当前砝码重量
            else if (dp[i - 1][abs(j - w[i])] == 1)
                dp[i][j] = 1; //减去当前砝码重量(可能是砝码-物体也可能是物体减砝码)
            if (dp[n][j] == 1)
                ans++;//放完n个物品看看那些重量是符合的
        }
    }
    cout << ans << "c0re"<<endl;
    system("pause");
    return 0;
}

注意事项

首先在那四个状态的时候如果你这个第一个状态也就是不放砝码的状态也可以写成

if (j == w[i]) dp[i][j] = 1;

但这样写就会发生一个问题!有一些状态没有被记录,这个时候要把背包的遍历顺序反过来写


http://www.kler.cn/a/1829.html

相关文章:

  • C#连接SQLite数据库并实现基本操作
  • 论文研读:AnimateDiff—通过微调SD,用图片生成动画
  • apisix的hmac-auth认证
  • Java 中 getClass() 方法的使用与原理分析:深入理解对象类型信息
  • 机器学习系列(一)——K-近邻算法
  • [Python机器学习]:Anaconda3实践环境安装和使用
  • 可换皮肤的Qt登录界面
  • 【字符串】
  • 上手使用百度文心一言
  • 【SpringMVC】SpringMVC方式,向作用域对象共享数据(ModelAndView、Model、map、ModelMap)
  • 带你看看 TypeScript 5.0 的新特性
  • DJ2-4 进程同步(第一节课)
  • 【数据结构】二叉树(OJ)
  • C/C++每日一练(20230319)
  • 基于微信小程序的校园二手交易平台小程序
  • spark第三章:工程化代码
  • C语言预处理条件语句的 与或运算
  • Linux实操之进程管理
  • 咪咕MGV3201_ZG_GK国科6323_UWE5621DS_免拆卡刷固件包
  • 【springcloud 微服务】Spring Cloud Alibaba Sentinel使用详解
  • Transformer到底为何这么牛
  • C/C++ 内存分配 new操作符
  • Leetcode.1292 元素和小于等于阈值的正方形的最大边长
  • Thread的小补丁
  • 用Qt画一个温度计
  • 【MySQL】聚合查询