如何计算最优惠的价格

时间:2013-07-11 12:14:57

标签: algorithm graph dynamic-programming dijkstra knapsack-problem

我有一个有趣的问题。我想知道一些解决这个问题的好方法。

我有一家小商店,我有很多产品 每个产品都与non zero price相关联

产品看起来像这样

 { 
   productId:productA;  
   productName:ABC;    
   price:20$ 
}

为了提高客户保留率,我想引入组合模型进行销售。 那是, 我定义m number of combos

每个组合都是这样的

   {    
      comboId:1;        
      comboName:2;       
      constituentProducts: {Product1, Product2};        
      comboPrice: 10$
    }

每个组合都会告诉客户购买productAproductB,然后应用组合定义中给出的折扣价格,而不是productA和{{的单个价格的算术总和1}} 可以在两个以上的组合中提及产品。 计算购物篮的productB的最佳方法是什么

2 个答案:

答案 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那么你只需要总结列表中的所有项目,否则重复使用这个数字。

在第一次函数调用结束时,您应该在此减量结束时得到正确的答案!