cbm总和满足0.8±0.08时,如何选取组合实现最低price总和?
解决方案:满足CBM区间要求的最低总价组合选择
问题本质
这是一个0-1背包变种问题:从给定6行数据中选若干行,要求选中行的CBM总和落在0.72~0.88区间(0.8±0.08),同时总价最小。你的思路(用0/1标记选中状态,筛选符合CBM条件的组合后取总价最低)完全正确,且由于数据量极小(仅6行,总组合数2^6=64种),直接枚举所有子集是最简便高效的方法。
手动验证最优组合
逐一计算所有非空子集的CBM总和与总价,筛选符合条件的组合后对比:
- 行1+2+3+4:CBM总和
0.24+0.14+0.21+0.18=0.77(在允许区间内),总价500+400+610+300=1810 - 行1+3+4+5:CBM总和0.75,总价1850
- 行1+2+4+6:CBM总和0.8,总价1960
- 其他符合条件的组合总价均高于1810
因此,行1、2、3、4的组合是最优解,既满足CBM要求,又实现了最低总价。
自动化计算代码(Python)
如果需要快速验证或后续数据量调整,可使用以下代码自动枚举所有组合:
# 原始数据:(cbm, price) data = [ (0.24, 500), (0.14, 400), (0.21, 610), (0.18, 300), (0.12, 440), (0.24, 760) ] # CBM允许范围 target_cbm_min = 0.8 - 0.08 target_cbm_max = 0.8 + 0.08 min_total_price = float('inf') best_selection = [] # 枚举所有非空子集(二进制掩码表示选中状态) for mask in range(1, 1 << len(data)): current_cbm = 0.0 current_price = 0 selected_rows = [] for idx in range(len(data)): if mask & (1 << idx): current_cbm += data[idx][0] current_price += data[idx][1] selected_rows.append(idx + 1) # 行号从1开始 # 检查CBM是否符合要求 if target_cbm_min <= current_cbm <= target_cbm_max: if current_price < min_total_price: min_total_price = current_price best_selection = selected_rows # 输出结果 print(f"最优选中行:{', '.join(map(str, best_selection))}") print(f"总CBM:{sum(data[row-1][0] for row in best_selection):.2f}") print(f"最低总价:{min_total_price}")
运行后输出:
最优选中行:1, 2, 3, 4 总CBM:0.77 最低总价:1810
大数据量优化方案
如果后续数据行数超过20行,枚举法效率会下降,可改用动态规划:
- 定义
dp[i][j]为前i行中,CBM总和接近j时的最小总价 - 遍历每行数据更新dp数组,最终在
0.72~0.88区间内找到最小总价对应的组合
但当前6行规模下,枚举法完全足够,无需复杂优化。
内容的提问来源于stack exchange,提问作者Song_Rui123
相关产品推荐
相关产品推荐

