集装箱海运配载问题:修正重复元素并找出全部符合载重的组合
集装箱运输载重组合优化问题
我们在两国间开展集装箱运输,拥有一组不同重量的集装箱,目标是通过最小化运输次数降低系统成本。船舶每次运输的集装箱载重限制为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)]
存在的问题
- 输出结果中出现重复使用同一集装箱的情况(如29同时出现在两个组合中,但原列表里29仅存在一个),不符合实际运输中每个集装箱只能被运输一次的要求。
- 当前仅找到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组互不重叠的有效组合:
- (29, 51) → 和为80
- (13, 22, 45) → 和为80
- (19, 32) → 和为51
- (43, 31) → 和为74
- (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
相关产品推荐
相关产品推荐

