我有一个有趣的问题。我想知道一些解决这个问题的好方法。
我有一家小商店,我有很多产品
每个产品都与non zero price
相关联
产品看起来像这样
{
productId:productA;
productName:ABC;
price:20$
}
为了提高客户保留率,我想引入组合模型进行销售。
那是,
我定义m number of combos
每个组合都是这样的
{
comboId:1;
comboName:2;
constituentProducts: {Product1, Product2};
comboPrice: 10$
}
每个组合都会告诉客户购买productA
和productB
,然后应用组合定义中给出的折扣价格,而不是productA
和{{的单个价格的算术总和1}}
可以在两个以上的组合中提及产品。
计算购物篮的productB
的最佳方法是什么
答案 0 :(得分:0)
如何计算最佳价格
看起来这个算法将运行多次。 所以我可以随意使用eavy预计算步骤(对不起,如果不是这样的话)。
计算最优价格,是通过应用来计算组合组合。 所以我只打印可以应用的组合。
定义thoses类型 以sml表示法
type index = (productId, tag) Hashtbl.t
and tag = {
combos : combo list [default is empty list]
subIndex : index [default is empty hash]
}
and combo = {
comboId : int;
comboName : string
constituentProducts : list product;
comboPrice : int
}
and product = {
productId : int;
productName : string,
price : int (*In fact as I understand the problem this price don't change any thing. *)
}
预计算步骤是建立索引。
通过productsId对组合中的所有产品进行排序。的重要强>
let insertIntoIndex(Index index, Combo combo, int level = 0) ->
assert level < combo.constituentProducts.length;
tag entry = index[combo.constituentProducts[level].productId];
if entry is null/notFound then { entry = new tag(); }
if level + 1 == combo.constituentProducts.length
then
{
entry.combos.add combo;
}
else
{
if null/notFound = entry.subIndex.get(combo.constituentProducts[level])
then entry.subIndex.add (combo.constituentProducts[level].productId) (new tag());
insertIntoIndex(entry.subIndex, combo, level+1)
}
iter insertIntoIndex over the all combo,对于相同的索引。
正如您所看到的,这个索引是一种树形式。 每个节点都可以算一个组合并成为更大组合的一部分。
将所有篮子产品放入一个数组中(如果需要,重复);
按照用于排序组合的顺序对productId排序该数组。的重要强>
for(int position = 0; position < array.length ; position++)
scan(index, product, position);
let scan(index,product, position) ->
entry = index.get array[position];
if entry != null/notfound
then
{
iter print entry.combos; (* or build a set of result *)
foreach(product key : entry.subIndex.keys)
{
positionOfFoundKey = array.find(from = position, to = length-1 , look = key )
if (positionOfFoundKey != -1) (* -1 for not found / null is the find function *)
scan(entry.subIndex[key], array[positionOfFoundKey], positionOfFoundKey)
}
}
当产品被分类时,除非组合确实存在,否则将没有两次组合计数。 您可以通过添加包来找到匹配产品来改善扫描功能,从包中取出已扫描的产品。
搜索的复杂性:
n x scan
扫描的复杂性:
size of bucket x maximum size of combo x number of combo
我认为这只是一个永远不应该附加的上限。
我不知道它是否是最好的,但它看起来很快,因为我不知道你的输入是什么样的。
答案 1 :(得分:0)
有一个HashMap,其键是组合中的产品数量,其值是另一个HashMap&lt;按字母顺序排序的产品列表,组合&gt;。
HashMap<Integer, HashMap<List<Products>, Combo>> comboMap;
现在按字母顺序对购物车中的产品进行排序,并跟踪当前看到的最低价格以及与该价格相关联的组合列表:
float lowestCurrentPrice;
List<Combo> minComboList;
具有递归功能,该功能以组合中最高可能数量的产品或列表大小开头,并尝试在购物车中找到包含该数量产品的组合。
如果找到,请删除组合中的产品,跟踪组合的成本,并将其添加到现在使用较小列表重复的递归函数的结果中。
如果您已经找到了包含该数量产品的组合,请比较两个价格并保留HashMap中较便宜的组合列表。
这样做直到你用完该数字的组合。然后,您在组合中减少要查找的项目数。如果这个数字是1那么你只需要总结列表中的所有项目,否则重复使用这个数字。
在第一次函数调用结束时,您应该在此减量结束时得到正确的答案!