【华为OD-E卷 - 81 会议接待 100分(python、java、c++、js、c)】

【华为OD-E卷 - 会议接待 100分(python、java、c++、js、c)】

题目

某组织举行会议,来了多个代表团同时到达,接待处只有一辆汽车,可以同时接待多个代表团,为了提高车辆利用率,请帮接待员计算可以坐满车的接待方案,输出方案数量。
约束:
一个团只能上一辆车,并且代表团人数 (代表团数量小于30,每个代表团人数小于30)小于汽车容量(汽车容量小于100) 需要将车辆坐满

输入描述

  • 第一行 代表团人数,英文逗号隔开,代表团数量小于30,每个代表团人数小于30

第二行 汽车载客量,汽车容量小于100

输出描述

  • 坐满汽车的方案数量,如果无解输出0

用例

用例一:
输入:
5,4,2,3,2,4,9
10
输出:
4

说明 解释 以下几种方式都可以坐满车,所以,优先接待输出为4

[2,3,5]

[2,4,4]

[2,3,5]

[2,4,4]

python解法

  • 解题思路:
  • 本题是一个经典的 背包问题(类似于子集和问题),目的是计算从给定的 nums 数组中选择若干个数,使得它们的和等于 target(即 bag),并返回符合条件的组合数量。

这个问题通过 动态规划(DP)来解决。我们利用递归来枚举所有的选择,使用记忆化递归来避免重复计算,提高效率。

解题步骤
递归问题建模:

我们要递归地选择每个数,要么包括它(从 nums[i] 中选一个),要么不包括它。每次选择后,问题的规模会减少。
如果当前已经找到了满足条件的组合(即剩余的目标和 remaining 为 0),则返回 1。
如果剩余目标 remaining 小于 0 或者已经遍历完所有元素,则返回 0。
记忆化递归:

为了避免重复计算,我们使用 lru_cache 对递归结果进行缓存,这样相同的子问题只会被计算一次。
递归函数 dp(i, remaining) 的定义:

i 是当前处理的数组索引。
remaining 是当前剩余需要求和的目标值。
状态转移:

对于每个索引 i,我们有两种选择:
包括 nums[i],目标值变为 remaining - nums[i],继续递归。
不包括 nums[i],继续递归。
最终的返回值是这两者的和。
输入输出:

输入 nums 是一个整数列表,bag 是目标和。
输出是符合条件的组合数量。

from functools import lru_cache  # 引入lru_cache用于缓存递归结果,优化性能

def find_combinations(nums, target):
    # 使用lru_cache装饰器,缓存递归结果,None表示不限制缓存的数量
    @lru_cache(None)
    def dp(i, remaining):
        # 如果剩余目标为0,说明当前组合已经满足条件,返回1
        if remaining == 0:
            return 1
        # 如果剩余目标小于0或者已经遍历完所有元素,返回0
        if remaining < 0 or i == len(nums):
            return 0
        # 递归两种选择:选择当前元素nums[i],或者不选择当前元素
        include = dp(i + 1, remaining - nums[i])  # 包括当前元素
        exclude = dp(i + 1, remaining)           # 不包括当前元素
        # 返回包括和不包括当前元素的总和
        return include + exclude

    # 调用dp函数,从第一个元素开始,目标和为target
    return dp(0, target)

# 读取输入
nums = list(map(int, input().split(",")))  # 输入nums列表
bag = int(input())  # 输入目标和bag

# 输出符合条件的组合数量
print(find_combinations(tuple(nums), bag))  # 将nums转换为元组传递给dp函数,因为lru_cache要求不可变类型

java解法

  • 解题思路
  • 本题的目的是计算给定整数数组 nums 中可以组合出目标值 target 的组合数量。这是一个典型的 背包问题,其中我们可以选择或不选择每个数字,并且需要找出所有符合目标和的组合。

动态规划解法(记忆化递归)
递归建模:

我们要递归地计算:从数组的第 i 个元素开始,目标和是 remaining 时,符合条件的组合数量。
每个数字有两种选择:要么包括当前数字,要么不包括当前数字。
如果剩余目标和 remaining == 0,则返回 1,表示找到了一种组合。
如果 remaining < 0 或者遍历完所有数字,则返回 0,表示当前路径无解。
记忆化递归:

由于存在重复子问题,使用 HashMap 来缓存计算过的结果,避免重复计算。使用 (i, remaining) 作为缓存的键,i 表示当前处理的数字索引,remaining 表示剩余的目标和。
递归过程:

对于每个索引 i,我们有两种选择:
包括 nums[i],递归处理剩余目标 remaining - nums[i]。
不包括 nums[i],递归处理目标和 remaining。
最终返回两者的和,表示包括和不包括当前数字的所有组合。

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

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

        // 读取输入的整数数组
        String[] input = scanner.nextLine().split(",");
        int[] nums = new int[input.length];
        for (int i = 0; i < input.length; i++) {
            nums[i] = Integer.parseInt(input[i].trim());  // 将输入的字符串数组转换为整数数组
        }

        // 读取目标和
        int target = Integer.parseInt(scanner.nextLine());

        // 创建一个 Main 实例并调用 findCombinations 方法
        Main solution = new Main();
        int result = solution.findCombinations(nums, target);

        // 输出结果
        System.out.println(result);
    }

    // 存储中间结果的哈希表,用于记忆化递归
    private Map<String, Integer> memo = new HashMap<>();

    // 主方法:调用递归方法 dp 来计算组合数量
    public int findCombinations(int[] nums, int target) {
        return dp(nums, 0, target);  // 从数组的第一个元素开始,目标和为 target
    }

    // 递归方法:dp(i, remaining) 表示从索引 i 开始,目标和剩余为 remaining 时的组合数量
    private int dp(int[] nums, int i, int remaining) {
        // 如果剩余目标和为0,说明找到了一个符合要求的组合,返回1
        if (remaining == 0) {
            return 1;
        }

        // 如果剩余目标和小于0,或者遍历到数组的末尾,则说明无解,返回0
        if (remaining < 0 || i == nums.length) {
            return 0;
        }

        // 创建一个缓存键,键值为当前索引和剩余目标和
        String key = i + "," + remaining;

        // 如果当前状态已经计算过,直接返回缓存结果
        if (memo.containsKey(key)) {
            return memo.get(key);
        }

        // 递归两种情况:包括当前数字 nums[i],或者不包括当前数字
        int include = dp(nums, i + 1, remaining - nums[i]);  // 包括当前数字
        int exclude = dp(nums, i + 1, remaining);            // 不包括当前数字

        // 将当前结果存入缓存
        int result = include + exclude;
        memo.put(key, result);

        // 返回当前状态的结果
        return result;
    }
}

C++解法

  • 解题思路
更新中

C解法

  • 解题思路

更新中

JS解法

  • 解题思路

更新中

注意:

如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏

你可能感兴趣的:(算法题,华为od,(A+B+C+D+E,卷)收录分享,java,华为od,python,c++,javascript)