动态规划-01-称砝码

1. 题目描述

对于给定的 n n n种砝码,重量互不相等,依次为 m 1 , m 2 , . . . , m n m_1,m_2,...,m_n m1,m2,...,mn,数量依次为 x 1 , x 2 , . . . , x n x_1,x_2,...,x_n x1,x2,...,xn

现在要用这些砝码去称物体的重量(放在同一侧),问能称出多少种不同的重量。特别地,称重重量包括0。

输入描述
第一行输入一个整数 n ( 1 ≦ n ≦ 10 ) n (1≦n≦10) n(1n10)代表砝码的个数。
第二行输入 n n n 个整数 m 1 , m 2 , . . . , m n ( 1 ≤ m 1 ≤ 2000 ) m_1,m_2,...,m_n(1 \leq m_1 \leq2000) m1,m2,...,mn(1m12000)代表每种砝码的重量。
第三行输入 n n n 个整数 x 1 , x 2 , . . . , x n ( 1 ≤ x i ≤ 10 ) x_1, x_2,...,x_n(1 \leq x_i \leq 10) x1,x2,...,xn(1xi10) 代表每种砝码的数量。

输出描述
输出一个整数,代表利用给定的砝码可以称出的不同的重量数。

示例1

输入:2
     1 2
     2 1
输出:5
说明:在这个样例中,有 2 个重量为 1 的砝码,1 个重量为 2 的砝码。称重方式如下:
     - 不放砝码,称重重量为 0 ;
     - 放 1 个重量为 1 的砝码,称重重量为 1 ;
     - 放 2 个重量为 1 的砝码,称重重量为 2 ;
     - 放 1 个重量为 1 的砝码、1 个重量为 2 的砝码,称重重量为 3 ;
     - 放 2 个重量为 1 的砝码、1 个重量为 2 的砝码,称重重量为 4 。
因此,能称出的不同重量有 5 种,分别是 0,1,2,3,4 。

2. 思路

  1. 将当前砝码,依据从1开始逐步累加到原有的数量,得到的结果放到set中(避免重量重复)
  2. 后面的砝码一次与前面砝码出现的重量结果进行依次累加,放入set中,重复的重量不需要计入
  3. 初始化set中的元素要考虑0的情况。
    在这里插入图片描述

3. 代码

注意遍历set的时候,如果还要修改,需要重新开辟一个副本来存储数据,否则会报错:
在这里插入图片描述

public static void main(String[] args) {
    Scanner in = new Scanner(System.in);

    while (in.hasNextInt()) {
        int n = in.nextInt();//不同重量砝码个数

        int[] m = new int[n];
        int[] x = new int[n];
        //重量
        for (int i = 0; i < m.length; i++) {
            m[i] = in.nextInt();
        }

        //数量
        for (int i = 0; i < x.length; i++) {
            x[i] = in.nextInt();
        }

        HashSet<Integer> possibleWeight = new HashSet<>();
        possibleWeight.add(0);//0也是一种可能性

        for (int i = 0; i < n; i++) {
            HashSet<Integer> currentSet = new HashSet<>(possibleWeight);
            for (int j = 1; j <= x[i]; j++) {
                for (Integer weight : currentSet) {
                    possibleWeight.add(weight + m[i]*j);
                }
            }
        }
        System.out.println(possibleWeight.size());
    }

}

以上为个人学习分享,如有问题,欢迎指出:)

### 关于拔河比赛中使用砝码重的01背包问题解决方案 在解决拔河比赛中涉及砝码重的问题时,可以将其建模为经典的01背包问题。该类问题的目标是在给定的一组物品中选取若干件放入容量有限的背包里,在不超过总重量限制的情况下使所选物品的价值最大化。 对于拔河比赛中的情况而言: - **物品**代表不同质量的砝码- **价值**即为这些砝码的质量本身; - 而所谓的“背包”,则是指拔河双方能够承受的最大重量差范围; 因此,目标就是找到一组砝码组合使得两队之间的重量差异最小化的同时不超出允许的最大偏差[^1]。 具体实现方法如下所示: ```python def min_weight_difference(weights, max_diff): n = len(weights) dp = [[False]*(max_diff + 1) for _ in range(n + 1)] sum_weights = sum(weights) # 初始化dp数组的第一列为True表示当没有选择任何砝码时, # 差异始终为零的情况是可以达到的状态。 for i in range(n + 1): dp[i][0] = True closest_sum_to_half = None for w in range(1, (sum_weights // 2)+1): if any(dp[j][(w - weights[j-1]) % (max_diff+1)] or not weights[j-1]<=w for j in range(1,n+1)): dp[w% (n+1)][w]=True if all(not dp[(k+1)% (n+1)][abs(sum_weights-(2*w))]for k in range(n)): closest_sum_to_half=w team_a_total=closest_sum_to_half team_b_total=sum_weights-team_a_total return abs(team_a_total-team_b_total),team_a_total,team_b_total weights=[1,3,5,7,9] max_allowed_difference=10 difference,a,b=min_weight_difference(weights,max_allowed_difference) print(f"The minimum weight difference between two teams is {difference}. Team A has total weight of {a}, while Team B has a total weight of {b}.") ``` 上述代码定义了一个名为`min_weight_difference` 的函数来计算两个队伍之间最接近的理想分配方式下的权重差距以及各自拥有的总重量。这里采用了动态规划算法来进行解,并通过调整参数适应不同的应用场景需[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值