根据给定条件创建最佳购物清单

时间:2015-10-07 21:24:36

标签: java optimization combinatorics

我正在尝试从一系列产品中创建购物清单,其中返回的购物清单应针对成本进行优化以及满足其他条件。

例如,假设我想根据产品的能源内容创建购物清单。当用户输入总金额时,返回的购物清单应该尝试最大化kcal内容,同时将总和保持在用户指定的总和处或附近。

我已经创建了产品集合,所有产品都存储为具有营养价值和价格等字段的对象.kcal值也作为成员变量存储在每个产品的对象中。 / p>

首先,我考虑循环浏览所有产品组合,对那些超出价格区间的产品进行排序,然后返回具有最高kcal含量的产品组合。但随着可用产品数量的增加,我认为这很快成为一种不可行的选择。

我现在想知道是否有任何算法可以解决这个问题,如果没有,有没有办法轻松实现这个?

1 个答案:

答案 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;
}