Если у вас есть монеты 15, 10, 6 и 2 цента, и вам нужно найти, сколько разных способов добраться до 50 вы можете
- посчитайте, сколько разных способов вам нужно достичь 50, используя только 10, 6 и 2
- посчитайте, сколько разных способов вам нужно достичь 50-15, используя только 10, 6 и 2
- посчитайте, сколько разных способов вам нужно достичь 50-15 * 2, используя только 10, 6 и 2
- посчитайте, сколько разных способов вам нужно достичь 50-15 * 3, используя только 10, 6 и 2
- Суммируйте все эти результаты, которые, конечно, различны (в первом я использовал не 15c монеты, во втором я использовал одну, в третьих два и в четвертой три).
Таким образом, вы можете разделить задачу на более мелкие задачи (возможно, меньшее количество и меньше монет). Когда у вас есть только один тип монет, ответ, конечно, тривиален (либо вы не можете точно набрать определенную сумму, либо можете только так).
Более того, вы также можете избежать повторения тех же вычислений, используя памятку, например, количество способов достижения 20 с использованием только [6, 2] не зависит от того, были ли достигнуты уже оплаченные 30 с использованием 15 + 15 или 10. + 10 + 10, поэтому результат меньшей задачи (20, [6, 2]) может
храниться и использоваться повторно.
В Python реализация этой идеи следующая
cache = {}
def howmany(amount, coins):
prob = tuple([amount] + coins) # Problem signature
if prob in cache:
return cache[prob] # We computed this before
if amount == 0:
return 1 # It's always possible to give an exact change of 0 cents
if len(coins) == 1:
if amount % coins[0] == 0:
return 1 # We can match prescribed amount with this coin
else:
return 0 # It's impossible
total = 0
n = 0
while n * coins[0] <= amount:
total += howmany(amount - n * coins[0], coins[1:])
n += 1
cache[prob] = total # Store in cache to avoid repeating this computation
return total
print howmany(50, [15, 10, 6, 2])