You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

技术问询:求解构建两个重量均不小于k的袋子所需的最少物品数量及递归实现疑问

嘿,我完全理解你的困惑!单个袋子的递归思路确实很直观,但要同时处理两个不相交的袋子,还要追踪已使用的物品,确实会多一层复杂度。咱们一步步拆解这个问题,找到可行的解决方案。

问题核心梳理

我们的目标是选出两个不重叠的物品子集,每个子集的总重量至少为k,要让两个子集的物品总数尽可能小。如果不存在这样的子集,返回-1。

解法思路:从单袋到双袋的递归扩展

你之前用递归解决单袋问题时,只需要追踪当前袋子的重量和处理到的物品索引。现在要处理双袋,我们可以扩展递归的状态,同时记录两个袋子的当前重量,以及已经使用的物品数量,这样就能避免重复使用物品了。

1. 带状态的递归(记忆化优化)

递归状态定义

我们的递归函数需要追踪四个参数:

  • index:当前处理到第几个物品(从0开始计数)
  • bag1:第一个袋子的当前总重量
  • bag2:第二个袋子的当前总重量
  • count:已经放入两个袋子的物品总数

递归逻辑

对于每个物品,我们有三种选择:

  • 不放任何袋子:直接递归处理下一个物品,袋子重量和计数都不变
  • 放入第一个袋子:如果第一个袋子还没达到k(已经达到的话再放只会浪费物品),就把当前物品加入第一个袋子,计数+1,递归处理下一个物品
  • 放入第二个袋子:同理,只有当第二个袋子未达标时才考虑放入,计数+1后递归处理下一个物品

终止条件

  1. 如果两个袋子的重量都≥k:记录当前的count,作为候选的最小物品数
  2. 如果已经遍历完所有物品:这条路径不可行,直接返回

剪枝优化

为了避免不必要的递归计算,我们可以在递归过程中加入剪枝:如果当前的count已经大于等于我们已经找到的最小物品数,就直接终止这条路径的递归——毕竟继续下去也不可能得到更优的结果。

代码示例(Python)

import sys
from functools import lru_cache

def min_items_for_two_bags(k, weights):
    total_sum = sum(weights)
    # 提前排除不可能的情况:总重量不够2k,直接返回-1
    if total_sum < 2 * k:
        return -1
    
    n = len(weights)
    min_total = sys.maxsize

    # 记忆化缓存,避免重复计算相同状态
    @lru_cache(maxsize=None)
    def dfs(index, bag1, bag2, count):
        nonlocal min_total
        # 剪枝:当前计数已经不优于已知最小值,直接返回
        if count >= min_total:
            return
        # 满足条件,更新最小计数
        if bag1 >= k and bag2 >= k:
            min_total = min(min_total, count)
            return
        # 遍历完所有物品,结束递归
        if index == n:
            return
        
        # 选择1:不放当前物品
        dfs(index + 1, bag1, bag2, count)
        # 选择2:放入第一个袋子(仅当袋子未达标时)
        if bag1 < k:
            dfs(index + 1, bag1 + weights[index], bag2, count + 1)
        # 选择3:放入第二个袋子(仅当袋子未达标时)
        if bag2 < k:
            dfs(index + 1, bag1, bag2 + weights[index], count + 1)
    
    dfs(0, 0, 0, 0)
    return min_total if min_total != sys.maxsize else -1

# 测试用例1
print(min_items_for_two_bags(4, [10]))  # 输出:-1
# 测试用例2
print(min_items_for_two_bags(2, [2,2,2]))  # 输出:2

2. 动态规划优化(适合较大物品数量)

如果物品数量N较大,递归可能会遇到栈溢出或效率问题,这时候可以用动态规划来优化。我们可以把状态压缩为dp[i][a][b],表示前i个物品中,第一个袋子重量为a、第二个袋子重量为b时的最小物品数。

为了压缩空间,我们可以把a和b的上限设为k——毕竟超过k的重量和刚好等于k的效果是一样的(都满足袋子的重量要求),这样能大幅减少状态数量。

边界情况处理

除了代码里的总重量检查,还要注意一些特殊情况:

  • 所有物品都大于k但数量不足2:比如k=4,物品[10],虽然总重量≥2k,但只有一个物品,无法分给两个袋子,返回-1
  • 单个物品就能满足一个袋子,但剩余物品无法凑够另一个袋子:比如k=5,物品[6,2,2],总重量10≥10,但剩余两个2的总和是4<5,所以返回-1

内容的提问来源于stack exchange,提问作者Dhairya Tripathi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 03:52:46