问题描述
categories
,其中包含任意数量的elements
。attributes
A,B和C.每个元素都有这些attributes
的其他分布。该分布通过正整数值表示。例如,元素1具有属性A: 42 B: 1337 C: 18
。这些属性的总和与元素不一致。有些元素比其他元素更多。现在出现问题:
我们希望从每个类别中选择一个元素,以便
示例:我们希望在所有选定的元素上总共至少达到80 A和150 B,并且希望尽可能多的C。
我已经考虑过这个问题,无法想象一个有效的解决方案。样本大小约为15个类别,每个类别包含多达30个元素,因此强制执行似乎不是非常有效,因为可能存在30 ^ 15种可能性。
我的模型是我认为它是一个深度类别数的树。每个深度级别代表一个类别,并让我们选择从该类别中选择一个元素。当遍历节点时,我们将表示元素的属性添加到我们想要优化的总和中。
如果我们在同一级别上多次点击相同的属性组合,我们将它们合并,以便我们可以去除已计算值的多次计算。如果我们达到一个路径,其中一个路径在所有三个属性中的值都较少,我们就不再遵循它了。
然而,在最坏的情况下,这棵树仍然有~30 ^ 15个节点。
你们有没有人能想到一个可以帮助我解决这个问题的算法?或者你能解释为什么你认为没有算法吗?
答案 0 :(得分:1)
此问题与knapsack problem的变体非常相似。我首先要看一下这个问题的解决方案,看看你能把它应用到你陈述的问题上。
答案 1 :(得分:0)
我的第一个倾向是尝试分支。你可以做到广度优先或深度优先,我更喜欢深度优先,因为我认为它更清洁。
为了简单地表达它,你有一个可以枚举所有可能性的树遍历程序walk
(也许它只有一个5级嵌套循环)。它增加了两件事:
在此过程的每一步,它都会跟踪cost
,此时费用只会增加。 (如果成本也可以降低,那就更像是一个极小极大的游戏树搜索。)
该程序有一个参数budget
,它不搜索费用可能超出预算的任何分支。
然后你有一个外循环:
for (budget = 0; budget < ... ; budget++){
walk(budget);
// if walk finds a solution within the budget, halt
}
预算所需的时间是指数级的,因此更容易的情况会花费更少的时间。您重新进行搜索的事实并不重要,因为预算的每个级别都会花费与之前所有级别相比更多或更多的时间。
将此与关于您考虑分支的顺序的某种启发式相结合,它可以为您提供一个可行的解决方案来解决您给出的典型问题。
如果不起作用,您可以依靠基本的启发式编程。也就是说,手工做一些案例,并注意你是如何做到的。然后以同样的方式编程。
我希望有所帮助。