Я пытаюсь unwind использовать функцию recursive в этом algorithm. Проблема обмена монет: при заданном количестве n и списке array различных номиналов монет, какое наименьшее количество монет необходимо для внесения суммы сдачи.

def rec_coin(target,coins):

    # Default to target value
    min_coins = target

    # Check to see if we have a single coin match (BASE CASE)
    if target in coins:
        return 1

    else:

        # for every coin value that is <= than target
        for i in [c for c in coins if c <= target]:

            # Recursive Call (add a count coin and subtract from the target) 
            num_coins = 1 + rec_coin(target-i,coins)

            # Reset Minimum if we have a new minimum
            if num_coins < min_coins:

                min_coins = num_coins

    return min_coins

# rec_coin(63,[1,5,10,25])
# 6

Это то, что я придумал после того, как разбил его на части

1 + 63-1 coins + 62-1 + 61-1 and so on..

Зачем нам прибавлять 1? Каким будет правильный способ отключить рекурсию

-2
edmamerto 13 Май 2018 в 09:05

1 ответ

Лучший ответ

Код, который вы представляете, очень неэффективен. Чтобы найти решение для суммы 63, представьте, что оно сначала рекурсивно перейдет к целевой сумме с шагами наименьшей монеты (т. Е. 1). Затем, после большого количества откатов и попыток с другими монетами, он, наконец, возвращается к самому внешнему уровню и пробует монету со значением 5. Теперь рекурсия снова запускается, как и раньше, добавляя монеты номиналом 1. Но проблема в том, что это промежуточное значение (63-5) уже было посещено ранее (на глубине 5 уровней после выбора монеты 1), и потребовалось много вызовов функций, чтобы получить результаты для этого значения 58. И все же алгоритм просто проигнорирует это и сделает все это снова работает.

Распространенным решением этой проблемы является динамическое программирование, то есть запоминание ранее найденных решений, чтобы их можно было повторно использовать без дополнительной работы.

Я представлю здесь восходящий метод: сначала он проверяет все суммы, которые могут быть получены с помощью одной монеты. Эти суммы ставятся в очередь. Если цель находится среди них, то ответ - 1. Если нет, все суммы в очереди обрабатываются путем добавления всех возможных монет к каждой из них. Иногда будет найдено значение, которое уже было посещено ранее, и в этом случае оно не помещается в следующую очередь, но в противном случае это так. Если теперь целевое значение находится в этой очереди, вы знаете, что цель может быть достигнута всего за 2 монеты.

Этот процесс продолжается в цикле, который на самом деле представляет собой просто поиск в ширину в дереве, где суммы являются узлами, а ребра представляют, что одна сумма может быть достигнута из другой, добавив к ней одну монету. Поиск начинается с узла, представляющего сумму 0.

Вот код для этого:

def rec_coin(target, coins):
    visited = set() # Amounts that we have already achieved with a minimal number of coins
    amounts = [0] # The latest series of amounts all using an equal number of coins
    for min_coins in range(1, target+1):
        next_amounts = []
        for amount in amounts:
            for coin in coins:
                added = amount + coin
                if added == target: 
                    return min_coins
                if not added in visited:
                    visited.add(added)
                    next_amounts.append(added)
        amounts = next_amounts

print (rec_coin(63,[1,5,10,25]))
1
trincot 13 Май 2018 в 12:27