我正在尝试开发一种算法,从较大的列表中选择一个活动子集。如果选择,则每个活动使用一定量的固定资源(即,所选活动的总和必须保持在总预算之下)。可能有多个可行的子集,从中选择的方法将基于计算未选择的活动的机会成本。
编辑:这不是0-1 knapsack problem有两个原因:
O(2^n)
。我所做的研究表明了一种天真的方法:
定义powerset
对于powerset的每个元素,根据不在集合中的项目计算它的效用 选择具有最高实用程序的元素
但是,我知道有办法加快执行时间和所需的内存。例如:
O(2^n)
,但我不需要完全枚举列表,因为一旦我发现一组超出预算的任务,我知道任何添加更多任务的集合都是不可行的并且可以被拒绝。也就是说,如果{1,2,3,4}
不可行,{1,2,3,4} U {n}
也是如此,其中n是较大列表中剩余的任务之一。{1,2,3}
是否可行,{2,1,3}
,{3,2,1}
等也是如此。 我已经说服自己一个好的递归算法会起作用,但我无法弄清楚如何定义它,即使在伪代码中(这可能是最有意义的,因为它将以几种语言实现) - 可能是Matlab用于原型设计,然后是编译语言)。
答案 0 :(得分:2)
knapsack problem是NP完全的,这意味着没有有效的方法来解决问题。然而,有一个使用动态编程的伪多项式时间解决方案。有关详细信息,请参阅其上的Wikipedia section。
但是,如果最大效用很大,则应该使用近似算法。一种这样的近似方案是贪婪地选择具有最大效用/成本的项目。如果预算很大并且每个项目的成本很小,那么这可以很好地解决。
编辑:由于您根据不在集合中的项目定义实用程序,因此您可以简单地重新定义成本。否定成本,然后改变一切,使你的所有价值观都是积极的。
答案 1 :(得分:1)
正如其他人所提到的,你正试图解决一些背包问题。虽然从理论上讲,你注定要失败,但在实践中你仍然可以做很多事情来提高算法的性能。以下是一些(各种各样的)想法:
{1, 2, 3, 4}
作为解决方案,{1, 2, 3, 4} u {n}
就不值得关注。< / LI>
NP
- 多项式时间中的问题,并且所有执行中1%(或任何您认为“足够安全”)的失败风险。(请记住:知道停止问题不可解决是一回事,而另一个问题是构建一个程序来确定“hello world”实现是否会以无限的方式运行。)
答案 2 :(得分:0)
我认为以下迭代算法将遍历整个解决方案集并存储任务列表,执行它们的总成本以及未执行任务的机会成本。
似乎它将在伪多项式时间内执行:活动数量的多项式和可以在预算范围内的活动数量的指数。
ixCurrentSolution = 1
initialize empty set solution {
oc(ixCurrentSolution) = opportunity cost of doing nothing
tasklist(ixCurrentSolution) = empty set
costTotal(ixCurrentSolution) = 0
}
for ixTask = 1:cActivities
for ixSolution = 1:ixCurrentSolution
costCurrentSolution = costTotal(ixCurrentSolution) + cost(ixTask)
if costCurrentSolution < costMax
ixCurrentSolution++
costTotal(ixCurrentSolution) = costCurrentSolution
tasklist(ixCurrentSolution) = tasklist(ixSolution) U ixTask
oc(ixCurrentSolution) = OC of tasks not in tasklist(ixCurrentSolution)
endif
endfor
endfor