仅限于 N 元解的背包算法

Posted

技术标签:

【中文标题】仅限于 N 元解的背包算法【英文标题】:Knapsack algorithm restricted to N-element solution 【发布时间】:2016-01-24 19:51:06 【问题描述】:

这段 CRAN 文档中关于 adagio 函数 knapsack() 的摘录按预期运行——它解决了具有利润向量 p、权重向量 w 和容量 cap 的背包问题,选择元素的子集在所选元素的总重量不超过容量的约束下获得最大利润。

library(adagio)
p <- c(15, 100, 90, 60, 40, 15, 10,  1)
w <- c( 2,  20, 20, 30, 40, 30, 60, 10)
cap <- 102
(is <- knapsack(w, p, cap))

如何在解决方案中添加向量长度约束并仍然获得最佳答案?例如上面的练习,但是选择的子集必须恰好包含三个元素。

【问题讨论】:

【参考方案1】:

一种方法是将问题显式建模为混合整数线性规划问题;以这种方式对其进行显式建模的优点是,像“恰好选择三个对象”这样的线性约束很容易建模。这是 R 中 lpSolve 包的示例,其中背包问题中的每个元素都由混合整数线性规划公式中的二进制变量表示。我们恰好选择三个元素的要求被要求决策变量总和恰好为 3 的约束所捕获。

library(lpSolve)
p <- c(15, 100, 90, 60, 40, 15, 10,  1)
w <- c( 2,  20, 20, 30, 40, 30, 60, 10)
cap <- 102
exact.num.elt <- 3
mod <- lp(direction = "max",
          objective.in = p,
          const.mat = rbind(w, rep(1, length(p))),
          const.dir = c("<=", "="),
          const.rhs = c(cap, exact.num.elt),
          all.bin = TRUE)
# Solution
which(mod$solution >= 0.999)
# [1] 2 3 4

# Profit
mod$objval
# [1] 250

虽然从adagio:::knapsack 函数中将最优解设置为所需大小是一种合理的启发式方法,但对于所需的子集大小小于标准问题的最优解的基数的情况,存在最优解的示例标准背包问题的解和尺寸受限背包问题的最优解是不相交的。例如,考虑以下问题数据:

p <- c(2, 2, 2, 2, 3, 3)
w <- c(1, 1, 1, 1, 2, 2)
cap <- 4
exact.num.elt <- 2

在容量为 4 且没有尺寸限制的情况下,标准背包问题将选择利润为 2 和重量为 1 的四个元素,得到总利润 8。但是,在尺寸限制为 2 的情况下,最佳解决方案是选择利润为 2 的两个元素3 和权重 2,得到总利润 6。

【讨论】:

以上是关于仅限于 N 元解的背包算法的主要内容,如果未能解决你的问题,请参考以下文章

背包问题的算法

贪心算法_01背包问题_Java实现

算法基础背包

oj算法----动态规划----背包问题

动态规划之01背包问题(最易理解的讲解)

贪心算法在背包中的应用