我正在尝试从一系列产品中创建购物清单,其中返回的购物清单应针对成本进行优化以及满足其他条件。
例如,假设我想根据产品的能源内容创建购物清单。当用户输入总金额时,返回的购物清单应该尝试最大化kcal内容,同时将总和保持在用户指定的总和处或附近。
我已经创建了产品集合,所有产品都存储为具有营养价值和价格等字段的对象.kcal值也作为成员变量存储在每个产品的对象中。 / p>
首先,我考虑循环浏览所有产品组合,对那些超出价格区间的产品进行排序,然后返回具有最高kcal含量的产品组合。但随着可用产品数量的增加,我认为这很快成为一种不可行的选择。
我现在想知道是否有任何算法可以解决这个问题,如果没有,有没有办法轻松实现这个?
答案 0 :(得分:0)
我做了一些类似动态编程Wikipedia article on Dynamic Programming
的事情在以下成本和值中应该是相同长度的数组。可供选择的项目的长度。容量是您选择的所有项目成本的最大总和。它返回一个相同长度的布尔数组,决定是否接受该项目。
这个想法是创建一个包含子问题解决方案的表,然后可以用它来解决更大的问题。子问题只解决了同样的问题,但是列表较小,最初只有一个项目。该表包含每个重量最多i个项目可以获得的最佳值。当您向列表中添加一个潜在项目时,您将其值添加到上一个解决方案中,允许的权重减去您添加的权重,并检查是否比没有最后一个项目的前一个解决方案更好。创建最后一行后,您可以通过检查最后一行中值的差异来确定要采取的项目。
public boolean[] solve(int[] values, int[] costs, int capacity) {
boolean take[] = new boolean[values.length];
int min_cost = Integer.MAX_VALUE;
for (int i = 0; i < values.length; i++) {
if (costs[i] < min_cost) {
min_cost = costs[i];
}
}
int table[][] = new int[values.length][capacity + 1 - min_cost];
for (int i = 0; i < values.length; i++) {
int v = values[i];
int w = costs[i];
for (int j = 0; j < capacity - min_cost + 1; j++) {
int prev_value = 0;
int new_value = 0;
if (i > 0) {
prev_value = table[i - 1][j];
if (w <= j + min_cost) {
if (w <= j) {
new_value = table[i - 1][j - w] + v;
} else {
new_value = v;
}
}
} else if (w <= j + min_cost) {
new_value = v;
}
table[i][j] = Math.max(prev_value, new_value);
}
}
int index = capacity - min_cost;
for (int i = values.length - 1; i > 0 && index >= 0; i--) {
if (table[i][index] != table[i - 1][index]) {
take[i] = true;
index -= costs[i];
if (index < 0) {
System.err.println("index = " + index);
}
} else {
take[i] = false;
}
}
take[0] = index >= 0 && table[0][index] != 0;
return take;
}