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

如何将偶数元素集合划分为两个等元素子集且和尽可能接近?求算法

等大小子集和分割:近似与精确解法

这个问题属于等大小子集和分割问题,是经典NP难问题的变种——如果集合规模n不大(比如n≤40),我们可以用精确算法找到最优解;如果n很大,就用启发式近似算法快速得到接近最优的结果。

一、精确解法:动态规划

核心思路是跟踪两个状态维度:已选择的元素数量、已选元素的总和。我们用状态记录「选k个元素能否得到总和s」,最后在所有满足k=n/2的s中,找最接近总总和一半的那个。

伪代码实现

输入:集合S(元素为浮点数,长度n为偶数)
输出:两个子集A和B,各含n/2个元素,和尽可能接近

1. 计算集合总总和total_sum = sum(S)
2. 目标参考和target = total_sum / 2
3. 需要选择的元素个数k = n / 2

4. 初始化动态规划状态:用字典dp,key是已选元素个数,value是该个数能达到的所有和的集合
   - 初始时dp[0] = {0},其他key对应的集合为空

5. 遍历每个元素num in S:
   - 反向遍历i从k-1到0(避免重复选择同一个元素):
     - 如果i不在dp中,跳过
     - 遍历当前dp[i]中的所有和s:
       - 将s+num加入dp[i+1](如果dp[i+1]不存在则先创建空集合)

6. 在dp[k]的所有和s中,找到最接近target的那个,记为best_sum
7. 回溯找到对应的k个元素组成子集A,剩下的元素组成子集B
8. 返回A和B

针对示例的说明

你的示例集合总和是28.9,target是14.45。通过动态规划,我们会找到k=5时最接近14.45的和(14.5和14.4),然后回溯得到对应的两个子集。

二、近似解法:改进贪心算法(适合大规模n)

如果n很大,动态规划的时间/空间开销会爆炸,这时候可以用启发式贪心:先排序,再交替把最大元素分配给当前和较小的子集,最后再做局部调整优化。

伪代码实现

输入:集合S(元素为浮点数,长度n为偶数)
输出:两个子集A和B,各含n/2个元素,和尽可能接近

1. 将S按降序排序
2. 初始化子集A、B,初始和sumA=0,sumB=0
3. 遍历排序后的每个元素num:
   - 如果sumA <= sumB 且 len(A) < n/2:
       将num加入A,sumA += num
   - else if len(B) < n/2:
       将num加入B,sumB += num
   - else:
       // 如果其中一个子集已满,尝试调整:找A中比num小的元素,替换后让sumA和sumB更接近
       遍历A中的元素a:
           新sumA' = sumA - a + num
           新sumB' = sumB + a
           如果abs(new_sumA' - new_sumB') < abs(sumA - sumB):
               将a移到B,num加入A,更新sumA和sumB,跳出循环
       // 如果A里找不到合适的,尝试调整B
       遍历B中的元素b:
           新sumB' = sumB - b + num
           新sumA' = sumA + b
           如果abs(new_sumA' - new_sumB') < abs(sumA - sumB):
               将b移到A,num加入B,更新sumA和sumB,跳出循环

4. 返回A和B

这个方法在你的示例中,排序后的集合是[5.0,5.0,5.0,4.0,3.1,2.9,1.6,1.0,0.7,0.6],按照规则分配后会快速得到接近最优的结果,甚至直接命中最优解。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:39:42