动态编程:最小数量的硬币变为65美分

时间:2014-10-29 21:41:58

标签: algorithm dynamic-programming

我正在尝试使用动态编程来解决问题,问题如下:

给予无限量的硬币(便士,镍,一角钱,二角钱,四分之一) 值(1,5,10,20,25),请找到最小数量的硬币进行65美分的变化。 使用了哪些硬币(以及每种硬币的数量)?说明使用该表所需的表格 动态编程算法以及如何获得使用的硬币。

注意我不希望任何人为我说明整个表格,但是我仍然不知道如何填写表格来解决这个问题。

我知道我的桌子看起来有点像这样:

    5   10  15  20  25  30  35  40  45  50  55  60  65
1

5

10

20

25

(我省略了1,因为我知道这不是最佳解决方案) 我最初的想法是,这个表格会像这样填写:

    5   10   15  20  25  30  35  40  45  50  55  60  65
1

5   1    2   4   5    5   6  7   8    9  10  11  12  13

10  0    1   

20

25

当我必须走得更远时,我会被困在这里。我不认为我理解动态编程如何完全解决这个问题。我一直在读我的书,在线阅读,但我仍然有点困惑。

编辑:

感谢其中一个答案,这就是我制定解决方案的方法:

    5     10    15    20    25    30    35    40    45    50    55    60    65
1   

5   1           1                  1                             1           

10         1    1                       1                              1     

20                    1                       2     1                        2

25                          1      1    1           1      2     2     2     1

2 个答案:

答案 0 :(得分:1)

你做错了。列表示您必须返回的总变化,行单元格表示使用的某些硬币(便士,镍币,硬币,二角硬币,四分之一)的数量。

该算法的重点是返回最小数量的硬币。例如,如果更改为25,则应返回单个季度,而不是25个便士。您可以看到我在下表中使用了四分之一的25美分列。

在15更改列中的示例中,您使用的是4 x 5cents,这是次优的,因为您可以使用一个10美分的硬币和一个5的硬币来返回总共15个。在20美分列中你正在使用5 x 5美分的变化,这是不正确的,并且再次不是最佳的,因为你可以使用一枚20美分的硬币来回报20美分。

这是填充前5列的表格。你可以填补余下的内容:

    5   10   15  20  25  30  35  40  45  50  55  60  65
1

5   1        1     

10      1    1  

20               1

25                   1
--------------------------------------------------------
T   1   1    2   1   1

我在底部添加了一个T行来计算您用作更改的硬币总数。你的目标是获得最低分。每列可能在此行中编号。

答案 1 :(得分:0)

仍然使用动态编程,我会将问题建模为构建一个图表,其中节点是金额(节点N是N分),其中有5种类型的有向边,{1,5,10, 20,25},对应于硬币类型。

保持尚未找到最佳解决方案的节点的运行前沿。每次迭代时,边界上的最小节点必须是最优的,因此可以将其删除,在边界上添加最多5个新节点。

这是算法的Python:

def change(coins, target):
    nodes = {0: (0, None)}
    frontier = set([0])
    while True:
        n = min(frontier)
        frontier.remove(n)
        if n == target:
            break
        elif n > target:
            return None # Infeasible!
        count = nodes[n][0]
        for coin in coins:
            m = n + coin
            frontier.add(m)
            if not m in nodes or nodes[m][0] > count + 1:
                nodes[m] = (count + 1, n)
    m = target
    sol = {}
    while True:
        n = nodes[m][1]
        if n is None:
            break
        coin = m - n
        sol[coin] = sol.get(coin, 0) + 1
        m = n
    return sol

print change([1, 5, 10, 20, 25], 65)

输出为{25: 1, 20: 2}