选择最低成本的组合

时间:2014-01-29 09:46:06

标签: java algorithm minimum

我在不同的餐厅有不同商品的数据

    Rest    Item     Price
    ----------------------
    ABC     dosa      14
    ABC     idly      30
    ABC     idly+upma 25

    123     dosa      30
    123     idly      7
    123     upma      12

    XYZ     dosa      20
    XYZ     idly      12
    XYZ     upma      20
    XYZ     dosa+upma 30
    XYZ     dosa+idly+upma 40

Now I need to pickup a restaurant which gives me the best deal of "dosa+idly+upma" items.

从上面的例子:它将是餐厅“ABC”

我无法设计有效的方法或不知道该怎么做?有什么想法吗?

更新

这里的对象看起来像

Class Rest{
  Map<String,Integer> menu; //item,price map
}

5 个答案:

答案 0 :(得分:6)

此问题为NP-Hard 。我将从Set Cover Problem显示缩减。

设置封面问题(SCP):
给定一系列元素U(在您的示例中为U={dosa,idly,upma})和一组U子集,让它为S(例如{{1}找到S={{dosa}, {idly,upma}, {upma}}的最小子集数,使其联合等于S

减少:
鉴于UU设置封面问题,请在一家餐厅创建问题实例,以便{{1}中每个项目的价格 (一组一个或多个项目)是1。

现在,给出问题的最佳解决方案 - 尽可能最低的价格,基本上是覆盖'宇宙'所需的最小子集数量。
给定集合覆盖问题的最优解 - 所需集合的数量是子集的最小价格。

<强>结论: 由于我们已经看到有效地解决这个问题将有效地解决SCP,我们可以得出结论,问题是NP-Hard,因此没有已知的多项式解决方案(并且大多数人认为不存在)。 / p>

替代品正在使用启发式解决方案或蛮力解决方案(只是在指数时间内搜索所有可能性)。

答案 1 :(得分:1)

一个可能的贪婪算法的草图是:

  1. 遍历所有一元优惠(例如 dosa idly upma )以找到每个优惠。
  2. 遍历所有binaray(例如 idly + upma )/ third(...)优惠,比较它是否比一元优惠更便宜,如果是,则替换。
  3. 您仍然需要对提供的代码进行代码处理,但它不应该那么难。该算法将找到好的,但不是必要的最佳解决方案,并且可能适用于非常小的算法。

    实际上,您的问题与背包或TSP问题相比较,这些问题是NP完全,因此只能在指数时间内解决。如果您想要一个解决方案,请考虑阅读大量论文和编码。这是计算机科学的圣杯。 ; - )

    更新:根据TO的请求,这里有一些指数伪代码草图:

    foreach restaurant
        create a list of all possible combinations of the offers // here's the exp!
        filter those combinations that hold more/less than 1 dosy/idly/umpa
        select minimum of the remaining ones
    

    评论:这真是太丑了,尤克! : - (

答案 2 :(得分:1)

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Mult {
    /**
     * @param args
     */
    public static void main(String[] args) {
        Map<String,List<X>> xx = new HashMap<String,List<X>>();
        xx.put("ABC",new ArrayList<X>());
        xx.get("ABC").add(new X("", 0));
        xx.get("ABC").add(new X("dosa", 14));
        xx.get("ABC").add(new X("idly", 30));
        xx.get("ABC").add(new X("idly+upma", 25));


        xx.put("123",new ArrayList<X>());
        xx.get("123").add(new X("", 0));
        xx.get("123").add(new X("dosa", 30));
        xx.get("123").add(new X("idly", 7));
        xx.get("123").add(new X("upma", 12));


        xx.put("XYZ",new ArrayList<X>());
        xx.get("XYZ").add(new X("", 0));
        xx.get("XYZ").add(new X("dosa", 20));
        xx.get("XYZ").add(new X("idly", 12));
        xx.get("XYZ").add(new X("upma", 20));
        xx.get("XYZ").add(new X("dosa+upma", 30));
        xx.get("XYZ").add(new X("dosa+idly+upma", 40));

        String[] t = {
                "dosaidlyupma",
                "idlydosaupma",
                "upmaidlydosa",
                "dosaupmaidly",
                "upmadosaidly",
                "idlyupmadosa"};
        Set<String> targets = new HashSet<String>(Arrays.asList(t));

        Map<String,Integer> best = new HashMap<String,Integer>();

        for(String restaurant:xx.keySet()){
            best.put(restaurant, Integer.MAX_VALUE);
            String combo = null;
            for(X a:xx.get(restaurant)){
                int deal = a.price;
                combo = a.item;
                for(X b:xx.get(restaurant)){
                    deal = deal + b.price;
                    combo = combo + "+" + b.item;
                    for(X c:xx.get(restaurant)){
                        deal = deal + c.price;
                        combo = combo + "+" + c.item;
                        if (targets.contains(combo.replaceAll("\\+", ""))){
//                          System.out.println(restaurant+"\t"+combo.replaceAll("\\+", "")+"\t"+deal);
                            if (best.get(restaurant) > deal){
                                best.put(restaurant, deal);                 
                            }
                        }
                    }
                }
            }
        }

        System.out.println(best);
    }

}

会给你

{XYZ = 40,ABC = 39,123 = 49}

这是旧的好蛮力方法。

不是最好的,但对于这个小套装,它可以工作。

答案 3 :(得分:0)

  1. 计算可能的价格组合:遍历地图并解析字符串。存储每个价格组合。

  2. 过滤掉更贵的价格。

  3. 比较每家餐厅的剩余价格,并以最便宜的价格退回餐厅。

  4. 您还可以进行一些检查以最小化迭代,例如:

    • 如果闲置是&gt;比起idly + umpa,不要计算任何涉及空闲的组合。

答案 4 :(得分:0)

首先,您需要对与不同的餐厅相对应的3个项目进行所有可能的组合,例如:

XYZ     dosa+idly+upma 52
XYZ     dosa+upma+idly 42
XYZ     dosa+idly+upma 40

与所有餐厅的情况相同。

然后对价格进行排序,让最低价格成为胜利。