给定多个金额和笔记列表(不能重复)。我需要找到笔记组合来赠送所有金额。
例如:如果备注为:
[1,1,5,6,6,8,8,10]
且金额为[15, 14, 16]
。解决方案可以是
{15:(10,5), 14:(6,8), 16:(1,1,6,8)}
这是变更问题的变体,如here所述。下面是使用动态编程进行标准变更问题的代码,给定V(无限面值集)和C(量)。如何修改非重复注释和多个金额。还需要每个金额的最终组合。
def min_change(V, C):
m, n = len(V)+1, C+1
table = [[0] * n for x in xrange(m)]
for j in xrange(1, n):
table[0][j] = float('inf')
for i in xrange(1, m):
for j in xrange(1, n):
aC = table[i][j - V[i-1]] if j - V[i-1] >= 0 else float('inf')
table[i][j] = min(table[i-1][j], 1 + aC)
return table[m-1][n-1]
更新
变更问题是NP完全的。这里有详细的论文http://www.or.deis.unibo.it/kp/Chapter5.pdf尽管如此,有一些解决方案是相当优化的,并且可以给出结果。
答案 0 :(得分:2)
正如@MissingNumber所述,它实际上可能比NP完全更糟糕。子集子问题会询问是否存在解决方案。该问题被视为NP-hard。您的问题实际上会提出更难的问题,即存在多少解决方案?这类问题属于P# (P-sharp)复杂性类,我认为它是P#完全,至少与NP完全版本一样难(并且可能更难)。
来自维基百科的一些例子来区分这两个类:
NP问题通常是这样的形式,"是否存在满足某些约束条件的解决方案?"
相应的#P问题询问"有多少"而不是"有没有"。例如:
答案 1 :(得分:0)
这是NP完全问题,请在以下网址找到最佳解决方案: