这是一个动态编程解决方案,它为ID的每个可能子集找到折扣最大的报价组合。这将是伪代码。
让我们的报价成为具有字段的结构
offerNumber,
setOfItems并且
discount。为了实现目的,我们首先通过从零到不同的可能项目数(例如
k)减去1
的整数重新枚举可能的项目。之后,我们可以
setOfItems用length的二进制数表示
k。例如,如果
k= 6和
setOfItems=
101110 2,则此集合包括项5、3、2 和1,不包括项4和0,因为位5、3、2 和1为1,而位4和0为零。
现在,让我们
f[s]成为使用确切
s项目集可获得的最佳折扣。在此,
s可以是0到2 k -1 之间的任何整数,代表2
k个可能的子集之一。此外,让
p[s]我们提供要约清单,这些清单可以使我们共同获得
f[s]一组商品的折扣
s。该算法如下。
initialize f[0] to zero, p[0] to empty listinitialize f[>0] to minus infinityinitialize bestF to 0, bestP to empty listfor each s from 0 to 2^k - 1: for each o in offers: if s & o.setOfItems == o.setOfItems: // o.setOfItems is a subset of s if f[s] < f[s - o.setOfItems] + o.discount: // minus is set subtraction f[s] = f[s - o.setOfItems] + o.discount p[s] = p[s - o.setOfItems] append o.offerNumber if bestF < f[s]: bestF = f[s] bestP = p[s]
之后,
bestF是可能的最佳折扣,并且
bestP是使我们获得折扣的优惠清单。
复杂度为O(| offers | * 2 k),其中
k为项目总数。
这是另一个实现,在渐近上是相同的,但是在大多数子集无法访问时,在实践中可能会更快。它是“向前”动态编程,而不是“向后”动态编程。
initialize f[0] to zero, p[0] to empty listinitialize f[>0] to -1initialize bestF to 0, bestP to empty listfor each s from 0 to 2^k - 1: if f[s] >= 0: // only for reachable s if bestF < f[s]: bestF = f[s] bestP = p[s] for each o in offers: if s & o.setOfItems == 0: // s and o.setOfItems don't intersect if f[s + o.setOfItems] < f[s] + o.discount: // plus is set addition f[s + o.setOfItems] = f[s] + o.discount p[s + o.setOfItems] = p[s] append o.offerNumber



