Предположим, что у меня есть набор монет, имеющих наименования a1, a2,... ak.
Известно, что один из них равен 1.
Я хочу сделать изменение для всех целых чисел от 1 до n, используя минимальное количество монет.
Любые идеи для алгоритма.
eg. 1, 3, 4 coin denominations
n = 11
optimal selection is 3, 0, 2 in the order of coin denominations.
n = 12
optimal selection is 2, 2, 1.
Примечание: не домашняя работа просто модификация эта проблема
Ответ 1
Это классическая проблема динамического программирования (заметим сначала, что жадный алгоритм здесь не всегда работает!).
Предположим, что монеты упорядочены так, что a_1 > a_2 > ... > a_k = 1
. Мы определяем новую задачу. Мы говорим, что проблема (i, j)
заключается в том, чтобы найти минимальное количество монет, внесших изменения для j
, используя монеты a_i > a_(i + 1) > ... > a_k
. Задача, которую мы хотим решить, (1, j)
для любого j
с 1 <= j <= n
. Скажем, что C(i, j)
является ответом на проблему (i, j)
.
Теперь рассмотрим экземпляр (i, j)
. Мы должны решить, используем ли мы одну из монет a_i
. Если это не так, мы просто решаем проблему (i + 1, j)
, а ответ - C(i + 1, j)
. Если да, то мы завершим решение, сделав замену для j - a_i
. Чтобы сделать это, используя как можно меньше монет, мы хотим решить проблему (i, j - a_i)
. Мы организуем так, чтобы эти две проблемы были решены для нас, а затем:
C(i, j) = C(i + 1, j) if a_i > j
= min(C(i + 1, j), 1 + C(i, j - a_i)) if a_i <= j
Теперь выясните, что такое начальные случаи и как перевести это на выбранный вами язык, и вам должно быть хорошо идти.
Если вы хотите попробовать свои силы в другой интересной проблеме, требующей динамического программирования, посмотрите Project Euler Проблема 67.
Ответ 2
Здесь приведен пример реализации алгоритма динамического программирования в Python. Это проще, чем алгоритм, описанный Джейсоном, поскольку он вычисляет только одну строку 2D-таблицы, которую он описывает.
Обратите внимание, что использование этого кода, чтобы обмануть домашнюю работу, заставит зомби Дейкстра кричать.
import sys
def get_best_coins(coins, target):
costs = [0]
coins_used = [None]
for i in range(1,target + 1):
if i % 1000 == 0:
print '...',
bestCost = sys.maxint
bestCoin = -1
for coin in coins:
if coin <= i:
cost = 1 + costs[i - coin]
if cost < bestCost:
bestCost = cost
bestCoin = coin
costs.append(bestCost)
coins_used.append(bestCoin)
ret = []
while target > 0:
ret.append(coins_used[target])
target -= coins_used[target]
return ret
coins = [1,10,25]
target = 100033
print get_best_coins(coins, target)