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

最大目标值求解:将线段长度数组划分为4个等和子集

解决思路

要找到最大的目标值T,使得数组中能选出4个不重叠子集,每个子集和为T,核心思路是从最大可能的T开始向下遍历,结合回溯+剪枝快速验证可行性。

步骤分解

  1. 预处理与边界判断

    • 将数组按降序排序:优先处理大元素,能快速排除不可能的T值,减少无效计算。
    • 计算数组总和sum_total,最大可能的T不超过sum_total // 4(因为4个T的和不能超过总长度)。
    • 过滤掉所有大于当前T的元素:单个元素超过T的话,无法加入任何子集,直接排除。
    • 如果过滤后的元素总和小于4*T,直接跳过当前T,因为凑不够4个和为T的子集。
  2. 回溯验证可行性
    用回溯法尝试将元素分配到4个“桶”中,每个桶的目标和为T,关键剪枝能大幅提升效率:

    • 剪枝1:如果当前桶加入元素后超过T,直接跳过该桶。
    • 剪枝2:如果当前桶和前一个桶的当前和相同,跳过该桶(避免重复计算相同状态)。
    • 剪枝3:如果将元素放入空桶后又回溯取出,说明该元素无法放入任何空桶,直接终止当前循环(其他空桶的情况完全一致)。

代码实现(Python)

def find_max_target(nums):
    nums.sort(reverse=True)
    total = sum(nums)
    # 从最大可能的T开始遍历
    for target in range(total // 4, 0, -1):
        # 过滤掉大于target的元素
        filtered = [num for num in nums if num <= target]
        if sum(filtered) < 4 * target:
            continue
        # 回溯验证
        if backtrack(filtered, 0, [0] * 4, target):
            return target
    return 0

def backtrack(nums, idx, buckets, target):
    if idx == len(nums):
        # 检查4个桶是否都达到目标
        return all(b == target for b in buckets)
    current_num = nums[idx]
    for i in range(4):
        # 剪枝1:当前桶加入元素后超过目标,跳过
        if buckets[i] + current_num > target:
            continue
        # 剪枝2:避免重复处理相同状态的桶
        if i > 0 and buckets[i] == buckets[i-1]:
            continue
        # 放入当前桶
        buckets[i] += current_num
        # 递归处理下一个元素
        if backtrack(nums, idx + 1, buckets, target):
            return True
        # 回溯
        buckets[i] -= current_num
        # 剪枝3:空桶放入元素后又取出,说明该元素无法放入任何空桶,直接终止
        if buckets[i] == 0:
            break
    return False

关键优化说明

  • 降序排序:大元素先处理,能快速发现无法凑出T的情况(比如第一个元素就放不进任何桶),直接剪枝后续递归。
  • 重复状态跳过:当多个桶当前和相同时,只需要尝试一次,避免重复计算相同的分配逻辑。
  • 空桶剪枝:如果元素放入空桶后无法完成分配,那么放入其他空桶也必然失败,直接终止循环,减少无效递归。

内容的提问来源于stack exchange,提问作者Pink Lem 15

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 02:35:09