繁体   English   中英

选择最低成本的组合

[英]Selecting A combination of minimum cost

我在不同的餐厅有不同项目的数据

    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
}

这个问题是NP-Hard 我将展示Set Set Problem的减少。

设置封面问题(SCP):
给定元素U的宇宙(在您的示例中U={dosa,idly,upma} )和U的子集的集合,则将其设为S (例如S={{dosa}, {idly,upma}, {upma}} )找出S的最小子集,使它们的并集等于U

减少:
给定US的“设置封面问题”,请为一个餐厅创建您的问题的实例,这样S中每个项目的价格 (是一个或多个项目的集合)为1。

现在,为您的问题提供最佳解决方案-可能的最低价格,基本上就是覆盖“宇宙”所需的最小子集数量。
给定布套问题的最佳解决方案-所需布套的数量是子集的最低价格。

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

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

一种可能的贪婪算法的示意图是:

  1. 遍历所有一元要约(例如dosaididupma )以找到每个中的最小值。
  2. 遍历所有binaray(例如idid + upma )/第三类(...)报价,比较它是否比一元报价便宜,如果可以,则进行替换。

您将必须编写代码以简化报价,但这并不难。 该算法将找到很好的解决方案,但不一定是最佳解决方案,并且可能在很小的样本上起作用。

实际上,您的问题与帆布背包或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

评论:这真的很丑,! :-(

尝试

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}

这是古老的强力手段。

不是最好的,但对于这种小型设备,它确实有效。

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

  2. 过滤掉更昂贵的价格。

  3. 比较每个餐厅的剩余价格,然后以最便宜的价格退还餐厅。

您还可以进行一些检查以最大程度地减少迭代,例如:

  • 如果idid>大于idid + umpa,则不要计算任何涉及idid的组合。

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

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

所有餐厅的上述情况均相同。

然后对价格进行排序,让最低价格重新赢得。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM