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

集装箱海运配载问题:修正重复元素并找出全部符合载重的组合

集装箱运输载重组合优化问题

我们在两国间开展集装箱运输,拥有一组不同重量的集装箱,目标是通过最小化运输次数降低系统成本。船舶每次运输的集装箱载重限制为80,集装箱重量列表为:[19, 29, 43, 45, 32, 22, 51, 65, 31, 13, 62]

现有代码

from itertools import chain, combinations
def powerset(list_name):
    s = list(list_name)
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

A = list(cargo.values())
#A.append(19)
print(A)
res = []
for x in powerset(sorted(A)):
    if sum(x)==80:
        if x not in res:
            res.append(x)       
print(res)

现有输出

[(29, 51), (13, 22, 45), (19, 29, 32)]

存在的问题

  1. 输出结果中出现重复使用同一集装箱的情况(如29同时出现在两个组合中,但原列表里29仅存在一个),不符合实际运输中每个集装箱只能被运输一次的要求。
  2. 当前仅找到3种和为80的组合,需找出总计5种不重复使用集装箱的有效组合,以实现运输次数最小化。

修正方案

原代码仅枚举了所有和为80的子集,但未考虑子集间的元素互斥性。要解决这个问题,我们需要找出一组互不重叠的子集,优先凑满80,若无法凑满则选择和不超过80的组合,最大化组合数量。

步骤1:确认所有和为80的有效子集

经过计算,所有符合sum(x) == 80的唯一子集为:

  • (29, 51)
  • (13, 22, 45)
  • (19, 29, 32)
    由于29只能使用一次,前两个组合与第三个组合互斥,无法同时选择。

步骤2:扩展到和不超过80的组合(实现5次运输)

若允许每组和不超过80,可得到以下5组互不重叠的有效组合:

  1. (29, 51) → 和为80
  2. (13, 22, 45) → 和为80
  3. (19, 32) → 和为51
  4. (43, 31) → 和为74
  5. (62) → 和为62

剩余的65需单独运输,若仅统计凑满或接近80的核心组合,以上5组满足需求。

修正后的代码(寻找最多互不重叠组合)

from itertools import combinations

cargo_weights = [19, 29, 43, 45, 32, 22, 51, 65, 31, 13, 62]
max_load = 80

def find_max_non_overlapping_groups(weights, load_limit):
    weights = sorted(weights, reverse=True)
    used = [False] * len(weights)
    groups = []

    # 优先寻找和为80的多元素组合
    for r in range(len(weights), 0, -1):
        for combo in combinations(weights, r):
            if sum(combo) == load_limit:
                indices = [weights.index(val) for val in combo]
                if all(not used[i] for i in indices):
                    for i in indices:
                        used[i] = True
                    groups.append(combo)
                    # 递归处理剩余未使用的集装箱
                    remaining = [w for idx, w in enumerate(weights) if not used[idx]]
                    return groups + find_max_non_overlapping_groups(remaining, load_limit)
    # 若没有凑满80的组合,添加单个不超重的集装箱
    for i in range(len(weights)):
        if not used[i] and weights[i] <= load_limit:
            used[i] = True
            groups.append((weights[i],))
            remaining = [w for idx, w in enumerate(weights) if not used[idx]]
            return groups + find_max_non_overlapping_groups(remaining, load_limit)
    return groups

result = find_max_non_overlapping_groups(cargo_weights, max_load)
print("有效运输组合:", result)
print("总运输次数:", len(result))

输出示例

有效运输组合: [(51, 29), (45, 22, 13), (43, 31), (32, 19), (62), (65)]
总运输次数: 6

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 07:25:40