获得阵列中最便宜的商品组合以达到给定的价值

时间:2019-05-20 19:36:52

标签: java algorithm search combinations

我正在尝试通过组合来解决问题:

我收到了一系列包含可用性百分比的产品,必须计算出最有效,最便宜的组合总和以获得给定的可用性百分比。有一些规则使其变得更困难。

鉴于以下问题:

[{
  "name": "network 1",
  "availability": 0.5,
  "cost": 20, 
 },               
 {
  "name": "network 2",
  "availability": 0.75,
  "cost": 30,
 }]

我需要使用以下公式找到最有效和最便宜的组合,以计算可用性: 1 - (1 - availability A) * (1 - availability B)… * (1 - availability n)

要求/规则:

  • 总可用性为0.9999(即99.99%)
  • 允许重复
  • 应该是cost方面最便宜的组合

最后,它应该打印用于解决方案的项目以及总成本。

我尝试使用有界/无界背包问题以及最小成本路径和子集总和来解决它,但找不到解决方案。同样在最后,它仅打印假定的解决方案,但我不知道如何获取用于获得该解决方案的物品。

最后,我回到了无限制的背包,因为它有很多重复,到目前为止,我已经做到了:

private static int max(int i, int j) {
        return (i > j) ? i : j;
    }

    private static int unboundedKnapsack(int W, int n, List<Long> val, List<Long> wt) {
        int dp[] = new int[W + 1];

        for(int i = 0; i <= W; i++){
            for(int j = 0; j < n; j++){
                if(wt.get(j) <= i){
                    dp[i] = max(dp[i], Math.toIntExact(dp[(int) (i - wt.get(j))] + val.get(j))); // TODO: can't figure out how to implement 1 - (1 - availability A) * (1 - availability B)… * (1 - availability n) instead.
                }
            }
        }

        return dp[W];
    }

    public static void main(String[] args) {
        String problem = "" +
                "[{\"function\":\"Server\", " +
                "\"name\":\"server 1\", " +
                "\"availability\":5, " +
                "\"cost\":10 }, " +

                "{\"function\":\"Server\", " +
                "\"name\":\"server 2\", " +
                "\"availability\":10, " +
                "\"cost\":30 }, " +

                "{\"function\":\"Server\", " +
                "\"name\":\"server 3\", " +
                "\"availability\":15, " +
                "\"cost\":20 }] ";

        JSONParser parser = new JSONParser();

        try{
            Object obj = parser.parse(problem);
            JSONArray array = (JSONArray) obj;

            List<Long> valArray = new ArrayList<>();
            List<Long> wtArray = new ArrayList<>();
            for (Object value : array) {
                JSONObject o = (JSONObject) value;

                Long cost = (Long) o.get("cost");
                valArray.add(cost);

                Long availability = (Long) o.get("availability");
                wtArray.add(availability);

            }

            int W = 100; // TODO: should be the required availability i.e 0.9999. Can't figure out how to get it to work with double values
            int n = valArray.size();
            System.out.println("cost: " + unboundedKnapsack(W, n, valArray, wtArray));
        } catch(ParseException pe) {
            System.out.println("position: " + pe.getPosition());
            System.out.println(pe);
        }
    }

目前,我仅将成本作为输出。因此,如果您运行代码ubove,则应该得到:

cost: 300

但是我想要实现的输出是这样的:

availability: 0.9999
items: server 1, server 2...
cost: 300

如果任何人都有解决此问题的算法的想法,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

可以使用类似于Is there any algorithm to address the longest common subsequent problem with different weights for each character?的想法通过动态编程来解决。

这个想法是您通过增加成本和增加可用性来建立一个表条目。每个条目包含以下数据:

total_cost: ...
total_availability: ...
last_item: ...
previous_entry:

请注意,previous_entry的数据类型是递归的,因此,从任何条目开始,您都可以按照链条进行操作,以获取包含的所有项目。

您的表开始时只有一个条目:

{total_cost: 0, total_availability: 0.0, last_item: null, previous_entry: null}

对于具有非零可用性的每个项目,请获取表中的每个现有元素,然后递归建立一系列具有可用性直至目标的条目。然后,您可以按成本升序然后按可用性降序对所有条目(包括之前的条目和创建的条目)进行排序。然后,仅使用那些元素重新构建表,以使没有等价或更低成本的元素具有更高的可用性,而所有可用性超过目标的元素都被视为处于目标可用性。

浏览完所有项目之后,表中至少包含目标可用性的条目将是您的答案,并且您可以递归地遍历previous_entry以找出需要哪些项目以及需要多少项目找到它。

这将花费时间,该时间是条目数量以及需要多少可能成本的多项式。