硬币变更优化

时间:2014-09-13 16:25:48

标签: dynamic-programming breadth-first-search greedy coin-change

我正试图解决这个问题:

  

假设我有一组n个硬币{a_1,a2,...,a_n}。有价值的硬币   始终会出现1。我最小的硬币数是多少   需要达到M?

     

约束是:

     
      
  • 1≤n≤25
  •   
  • 1≤m≤10^ 6
  •   
  • 1≤a_i≤100
  •   

好的,我知道这是变革问题。 我试图使用广度优先搜索,动态编程和贪婪来解决这个问题(这是不正确的,因为它并不总是提供最佳解决方案)。但是,我的时间限制超过了(3秒)。

所以我想知道这个问题是否有优化。 描述和约束引起了我的注意,但我不知道如何使用它对我有利:

  • 将始终显示值为1的硬币。
  • 1≤a_i≤100

我在维基百科上看到,这个问题也可以通过“使用概率卷积树进行动态编程”来解决。但我什么都听不懂。

你能帮帮我吗? 这个问题可以在这里找到:http://goo.gl/nzQJem

1 个答案:

答案 0 :(得分:1)

a_n成为最大的硬币。使用这两条线索:

  • 结果为>= ceil(M/a_n)
  • 结果配置有很多a_n's

最好尝试使用a_n's的最大值,然后检查它是否更好,结果少a_n's,直到可以找到更好的结果。

类似于:let R({a_1, ..., a_n}, M)是返回给定问题结果的函数。比R可以实现:

num_a_n = floor(M/a_n)
best_r = num_a_n + R({a_1, ..., a_(n-1)}, M-a_n*num_a_n)
while num_a_n > 0:
  num_a_n = num_a_n - 1
  # Check is it possible at all to get better result
  if num_a_n + ceil(M-a_n*num_a_n / a_(n-1) ) >= best_r:
     return best_r
  next_r = num_a_n + R({a_1, ..., a_(n-1)}, M-a_n*num_a_n)
  if next_r < best_r:
    best_r = next_r
return best_r