硬币改变,但每个硬币面额只有1

时间:2013-05-01 03:12:41

标签: algorithm dynamic-programming asymptotic-complexity correctness

问题是:

enter image description here

我提出的算法类似于:

pair<bool, bitmask>[n][A] memo;     
// memo[i][j].first will be true if its possible to 
// use up to i-th denomination for amt j
// memo[i][j].second will contain info on which 
// denominations are used
for i = 0 to n:
    for j = 1 to A:
    if (i==j): C[i][j] = {true, {i}}
    else if (C[i-1][j].first == true): C[i][j] = C[i-1][j]]
    else if (...see recurrance relation...): 
        C[i][j] = {true, C[i-1][j]+{denom[i]}}
    else: C[i][j] = false

到目前为止是否正确?但我不确定如何证明其正确性......我的尝试看起来只是用英语重写代码......

  

对于第一个如果:我们总是可以使用1个硬币的面额来解决   AMT = I。对于第一个,如果:如果我们有amt的解决方案没有   使用当前面额,我们可以重用,该解决方案。第二名   否则如果:如果可以使用当前面额(&lt; = amt),那么   不使用面额,我们可以......

对于复杂性:表的大小为nA。并且每个单元需要O(1)时间来填充。有人能指点我正确的方向吗?

1 个答案:

答案 0 :(得分:0)

是的,我会说你完全走在正确的轨道上。您解决的问题基本上是子集和问题,您的解决方案是标准的动态编程问题(参见http://en.wikipedia.org/wiki/Subset_sum_problem#Pseudo-polynomial_time_dynamic_programming_solution)。

就正确性而言,我会说解释递归关系和基本情况会很好。作为一个风格点,我不会通过代码来证明每一行,而是专注于大局。因此,只需解释一下您的表格代表什么以及如何设置基本案例和递归关系,读者可以轻松查看代码并看到您实现了这一点。

对于运行时:是的,您的算法只是循环遍历表格的元素并填写它们,因此您的解释是正确的。