import java.util.HashSet; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] m = new int[n]; // 砝码重量 int[] x = new int[n]; // 砝码数量 for (int i = 0; i < n; i++) { m[i] = sc.nextInt(); } for (int i = 0; i < n; i++) { x[i] = sc.nextInt(); } // 使用 HashSet 存储所有可能的重量 HashSet<Integer> possibleWeights = new HashSet<>(); possibleWeights.add(0); // 初始状态:不放砝码,重量为 0 for (int i = 0; i < n; i++) { // 遍历每种砝码 HashSet<Integer> temp = new HashSet<>(possibleWeights); // 避免遍历时修改 for (int weight : temp) { // 遍历当前所有可能的重量 for (int k = 1; k <= x[i]; k++) { // 尝试放 1 到 x[i] 个当前砝码 possibleWeights.add(weight + k * m[i]); } } } System.out.println(possibleWeights.size()); } }
动态规划(DP)解法思路
这道题可以用 动态规划(DP) 来解决,思路如下:
- 定义状态:dp[i] 表示是否能称出重量 i,true 表示可以,false 表示不可以。
- 初始化:dp[0] = true(因为不放砝码时,重量为 0)。
- 状态转移:遍历每种砝码 m_i,并遍历其数量 x_i。对于每一个可能的重量 j(从当前最大可能重量向下遍历,避免重复计算),如果能称出 j,那么加上 k 个 m_i 也能称出 j + k * m_i。
- 统计结果:最终 dp 数组中 true 的个数即为能称出的不同重量数。