【问题标题】:Creating optimal shopping list based on given conditions根据给定条件创建最佳购物清单
【发布时间】:2015-10-08 07:06:16
【问题描述】:

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

例如,假设我想根据产品的能量含量创建购物清单。当用户输入总和时,返回的购物清单应尽量将千卡内容最大化,同时将总和保持在用户指定的总和附近。

到目前为止,我已经创建了产品集合,所有产品都存储为对象,其中包含营养价值和价格等字段。千卡值也作为成员变量存储在每个产品的对象中。

一开始我考虑循环遍历所有的产品组合,把那些超出价格区间的,整理出来,然后返回kcal含量最高的那个。但随着可用产品数量的增加,我认为这很快就会成为一个不可行的选择。

我现在想知道有没有什么算法可以解决这个问题,如果没有,有什么方法可以轻松实现吗?

【问题讨论】:

  • 这更像是一个数学问题而不是算法问题。它看起来像一个线性问题,这是一类已知很多技术的问题。在您的特定情况下,解决方案是整数向量,因此可能会有些困难,但是我失去了太多的数学技能来告诉您
  • 是的,我脑海中突然出现的是丢番图方程求解,因为整数解是唯一可行的解​​。但除此之外,我一无所知。

标签: java optimization combinatorics


【解决方案1】:

我做了一些与动态编程类似的事情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;
}

【讨论】:

    猜你喜欢
    • 2013-11-03
    • 2018-08-03
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-24
    • 1970-01-01
    相关资源
    最近更新 更多