洛谷 砝码称重

洛谷 砝码称重

目录


题目描述

你有一架天平和 ( N ) 个砝码,这 ( N ) 个砝码重量依次是 ( W_1, W_2, \dots, W_N )。请你计算一共可以称出多少种不同的重量?注意砝码可以放在天平两边。


示例

示例 1

输入:

3
1 4 6

输出:

10

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


思路分析

问题核心

我们需要计算使用 ( N ) 个砝码,通过将它们放在天平的两边,可以称出多少种不同的重量。

思路拆解

  1. 初始化
    • 使用一个集合 set 来记录所有可能的重量,初始时集合中只有 0。
  2. 遍历砝码
    • 对于每个砝码,更新集合 set,将当前砝码的重量加到集合中的每个元素上,或者从集合中的每个元素中减去当前砝码的重量。
  3. 统计结果
    • 最终集合 set 的大小减去 1(去掉 0)就是可以称出的不同重量的数量。

代码段

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] dp = new int[n];
        for (int i = 0; i < n; i++) {
            dp[i] = sc.nextInt();
        }
        sc.close();
        Arrays.sort(dp);

        Set<Integer> set = new HashSet<>();
        set.add(0);
        for (int i = 0; i < dp.length; i++) {
            ArrayList<Integer> list = new ArrayList<>(set);
            for (int j : list) {
                set.add(j + dp[i]);
                set.add(Math.abs(j - dp[i]));
            }
        }

        System.out.println(set.size() - 1);
    }
}

在这里插入图片描述


代码逐行讲解

  1. 输入处理

    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    int[] dp = new int[n];
    for (int i = 0; i < n; i++) {
        dp[i] = sc.nextInt();
    }
    sc.close();
    Arrays.sort(dp);
    
    • 使用 Scanner 读取输入的整数 nn 个砝码的重量,并存储在数组 dp 中。
    • 对数组 dp 进行排序。
  2. 初始化集合

    Set<Integer> set = new HashSet<>();
    set.add(0);
    
    • 初始化一个集合 set,并添加初始值 0。
  3. 遍历砝码

    for (int i = 0; i < dp.length; i++) {
        ArrayList<Integer> list = new ArrayList<>(set);
        for (int j : list) {
            set.add(j + dp[i]);
            set.add(Math.abs(j - dp[i]));
        }
    }
    
    • 对于每个砝码,遍历集合 set 中的每个元素,将当前砝码的重量加到元素上,或者从元素中减去当前砝码的重量,并将结果添加到集合 set 中。
  4. 输出结果

    System.out.println(set.size() - 1);
    
    • 输出集合 set 的大小减去 1(去掉 0)作为结果。

复杂度分析

时间复杂度

  • 遍历每个砝码的时间复杂度为 O(N)
  • 对于每个砝码,遍历集合 set 的时间复杂度为 O(M),其中 ( M ) 是集合 set 的大小。
  • 因此,总时间复杂度为 O(N * M)

空间复杂度

  • 使用了一个集合 set 来存储所有可能的重量,空间复杂度为 O(M),其中 ( M ) 是集合 set 的大小。

总结的知识点

  1. 输入处理

    • 使用 Scanner 读取输入,并处理整数和数组。
  2. 集合操作

    • 使用 HashSet 来存储和更新所有可能的重量。
  3. 遍历与更新

    • 使用 for 循环遍历砝码和集合 set,并根据砝码的重量更新集合。
  4. 数学计算

    • 使用 Math.abs 计算绝对值,确保重量的非负性。

整合

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] dp = new int[n];
        for (int i = 0; i < n; i++) {
            dp[i] = sc.nextInt();
        }
        sc.close();
        Arrays.sort(dp);

        Set<Integer> set = new HashSet<>();
        set.add(0);
        for (int i = 0; i < dp.length; i++) {
            ArrayList<Integer> list = new ArrayList<>(set);
            for (int j : list) {
                set.add(j + dp[i]);
                set.add(Math.abs(j - dp[i]));
            }
        }

        System.out.println(set.size() - 1);
    }
}

总结

我们掌握了如何使用集合来记录所有可能的重量,并通过遍历和更新集合来计算可以称出的不同重量的数量。关键点包括:

  • 使用 HashSet 来存储和更新重量。
  • 遍历砝码和集合,并根据砝码的重量更新集合。
  • 使用 Math.abs 确保重量的非负性。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

学编程的小程

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

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

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

打赏作者

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

抵扣说明:

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

余额充值