Это запись - пример выгодного использование рекурсии. Тем, кто еще не ознакомился, советую прочитать - Линейные рекурсия и итерация. Чего не хватает Python. Я считаю, что именно в тематике динамического программирования рекурсия побеждает всех, как говорится "в шлемах и без" :) Тут я хочу рассмотреть всем известную(а может и не всем, раз вы читаете) задачу размена денег. У неё есть несколько интерпретаций, таких как:
Чтобы сочинить итеративный алгоритм для чисел Фибоначчи, нужно совсем немного смекалки. Теперь для контраста рассмотрим следующую задачу:
следующее уравнение:
Число способов разменять сумму a с помощью n типов монет равняется
Таким образом, мы можем рекурсивно свести задачу размена данной суммы к задаче размена меньших сумм с помощью меньшего количества типов монет. Внимательно рассмотрите это правило редукции и убедите себя, что мы можем использовать его для описания алгоритма, если укажем следующие вырожденные случаи:
Проверим countChange(100) - выдает нам 292 комбинации размена 100 центов.
Используемая литература:
- Как дать сдачу определенной суммы, определенным набором монет
- Сколькими способами конь может дойти до определенного места на шахмотной доске.
- И др.....
Чтобы сочинить итеративный алгоритм для чисел Фибоначчи, нужно совсем немного смекалки. Теперь для контраста рассмотрим следующую задачу:
Сколькими способами можно разменять сумму в 1 доллар, если имеются монеты по 50, 25, 10, 5 и 1 цент?В более общем случае, можно ли написать процедуру подсчета способов размена для произвольной суммы денег? У этой задачи есть простое решение в виде рекурсивной процедуры. Предположим, мы как-то упорядочили типы монет, которые у нас есть. В таком случае верно будет
следующее уравнение:
Число способов разменять сумму a с помощью n типов монет равняется
- числу способов разменять сумму a с помощью всех типов монет, кроме первого,плюс
- число способов разменять сумму a − d с использованием всех n типов монет, где d — достоинство монет первого типа.
Таким образом, мы можем рекурсивно свести задачу размена данной суммы к задаче размена меньших сумм с помощью меньшего количества типов монет. Внимательно рассмотрите это правило редукции и убедите себя, что мы можем использовать его для описания алгоритма, если укажем следующие вырожденные случаи:
- Если a в точности равно 0, мы считаем, что имеем 1 способ размена.
- Если a меньше 0, мы считаем, что имеем 0 способов размена.
- Если n равно 0, мы считаем, что имеем 0 способов размена.
def countChange(amount):
return cc(amount, 5)
def cc(amount, kindsOfCoins):
if amount==0:
return 1
if amount<0 or kindsOfCoins==0:
return 0
else:
return cc(amount, kindsOfCoins-1)+cc(amount-firstDenomination(kindsOfCoins), kindsOfCoins)
def firstDenomination(kindsOfCoins):
if kindsOfCoins==1:
return 1#1 цент
elif kindsOfCoins==2:
return 5#5 центов
elif kindsOfCoins==3:
return 10#10 центов
elif kindsOfCoins==4:
return 25#25 центов
else:
return 50#50 центов
Процедура firstDenomination принимает в качестве входа число доступных типов монет и возвращает достоинство первого типа. Здесь мы упорядочили монеты от самой крупной к более мелким, но годился бы и любой другой порядок.Проверим countChange(100) - выдает нам 292 комбинации размена 100 центов.
Используемая литература:

Комментариев нет:
Отправить комментарий