如何计算最优惠的价格
看起来这种算法将运行不止一次。所以我可以随意使用一个简单的预计算步骤(对不起,如果不是这样)。
计算最优惠的价格,就是计算组合比可以应用的组。所以我只打印可以应用的组合。
工作数据类型
用 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)
}
在所有组合上迭代 insertIntoIndex,以获得相同的索引。
如您所见,此索引是一种树形式。每个节点都可以计算一个组合并成为更大组合的一部分。
计算
将所有篮子产品放入一个数组中(如果需要可以重复);
按 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
我相信这只是一个永远不应该附加的上限。
我不知道它是否是最好的,但对我来说它看起来很快,因为我不知道你的输入是什么样的。