寻找最优作物组合的算法:最大化每日金币收益
问题分析与最优解法
这是一个带双重约束的0-1背包问题,核心约束有两个:
- 选中作物总耗水量 ≤ 当日供水上限(如100、130)
- 选中作物数量 ≤ 16(种植位限制)
目标是最大化总金币收益,暴力枚举完全不现实,以下是可行的高效解法:
核心解法:动态规划(DP)
1. 状态定义
定义二维数组 dp[k][w],其中:
k表示选中的作物数量(取值范围0~16)w表示总耗水量(取值范围0~当日供水上限)dp[k][w]对应状态下能获得的最大金币数
初始状态:dp[0][0] = 0(选0种作物,耗水0,收益0),其余状态初始化为不可达(比如用-∞表示)。
2. 状态转移
遍历每一种作物(记其产量为v,耗水量为c),倒序遍历k(从16到1),再倒序遍历w(从当日供水上限到c):
if dp[k-1][w - c] + v > dp[k][w]: dp[k][w] = dp[k-1][w - c] + v
倒序遍历是为了避免同一作物被重复选中(符合0-1背包“每种作物只能选一次”的要求)。
3. 结果计算
遍历所有k(116)和`w`(0当日供水上限),取dp[k][w]中的最大值,就是当日的最大金币收益。
额外优化技巧
- 空间压缩:可以将二维DP数组压缩为两个一维数组(分别存储前一个
k值的状态和当前k值的状态),大幅减少内存占用。 - 预处理剪枝:提前剔除耗水量超过当日供水的作物;对于耗水量相同的作物,只保留产量最高的那个(低产的不可能被选中)。
- 增量计算:如果每日供水逐步提升(如从100到130),可以复用之前计算的DP结果,只需要扩展
w的范围到新的供水上限,无需从头计算。
其他可选方法
- 分支定界法:适合快速找到近似最优解,在部分场景下效率可能优于DP,但对于本题的规模(50种作物、16个种植位、130供水上限),DP的效率已经足够。
- 贪心算法:仅适合快速估算,无法保证最优解。比如按“单位耗水量产量”排序选作物,可能会错过总收益更高的组合,不推荐用于追求最优解的场景。
内容的提问来源于stack exchange,提问作者user1600440
相关产品推荐
相关产品推荐

