我在不同的餐厅有不同商品的数据
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
}
答案 0 :(得分:6)
此问题为NP-Hard 。我将从Set Cover Problem显示缩减。
设置封面问题(SCP):
给定一系列元素U
(在您的示例中为U={dosa,idly,upma}
)和一组U
子集,让它为S
(例如{{1}找到S={{dosa}, {idly,upma}, {upma}}
的最小子集数,使其联合等于S
。
减少:
鉴于U
和U
设置封面问题,请在一家餐厅创建问题实例,以便{{1}中每个项目的价格 (一组一个或多个项目)是1。
现在,给出问题的最佳解决方案 - 尽可能最低的价格,基本上是覆盖'宇宙'所需的最小子集数量。
给定集合覆盖问题的最优解 - 所需集合的数量是子集的最小价格。
<强>结论:强> 由于我们已经看到有效地解决这个问题将有效地解决SCP,我们可以得出结论,问题是NP-Hard,因此没有已知的多项式解决方案(并且大多数人认为不存在)。 / p>
替代品正在使用启发式解决方案或蛮力解决方案(只是在指数时间内搜索所有可能性)。
答案 1 :(得分:1)
一个可能的贪婪算法的草图是:
您仍然需要对提供的代码进行代码处理,但它不应该那么难。该算法将找到好的,但不是必要的最佳解决方案,并且可能适用于非常小的算法。
实际上,您的问题与背包或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)
计算可能的价格组合:遍历地图并解析字符串。存储每个价格组合。
过滤掉更贵的价格。
比较每家餐厅的剩余价格,并以最便宜的价格退回餐厅。
您还可以进行一些检查以最小化迭代,例如:
答案 4 :(得分:0)
首先,您需要对与不同的餐厅相对应的3个项目进行所有可能的组合,例如:
XYZ dosa+idly+upma 52
XYZ dosa+upma+idly 42
XYZ dosa+idly+upma 40
与所有餐厅的情况相同。
然后对价格进行排序,让最低价格成为胜利。