Число способов разменять сумму Н
я столкнулся с этой проблемой:
http://www.geeksforgeeks.org/dynamic-programming-set-7-coin-change/
задано значение N, если мы хотим сделать изменение для N центов, и у нас есть бесконечный запас каждого из S = { S1, S2,.. , SM} ценные монеты, сколько способов мы можем внести изменения? Порядок монет не имеет значения.
например, для N = 4 и S = {1,2,3}, существует четыре решения: {1,1,1,1},{1,1,2},{2,2},{1,3}. Так выход должен быть 4. Для N = 10 и S = {2, 5, 3, 6}, существует пять решений: {2,2,2,2,2}, {2,2,3,3}, {2,2,6}, {2,3,5} и {5,5}. Таким образом, выход должен быть 5.
Я придумал решение:
// recurrence relation
count[N] = count[N-d] for all denomination <= N
Source code
-----------
public static int numWays(int N, int[] denoms) {
if (N == 0)
return 0;
int[] ways = new int[N+1];
ways[0] = 1;
for (int i=1; i<=N; i++) {
ways[i] = 0;
for (int d : denoms) {
if (d <= i) {
ways[i] += ways[i-d];
}
}
}
return ways[N];
}
но это дубликаты, которые имеют те же номиналы, но в другом порядке. Например, если номиналы = {1,2} и N=3, то это считается {1,1,1}, {2,1}, {1,2} который имеет повторяющуюся запись {1,2}.
Я вижу, что решение DP описано в ссылке здесь избегает повторений. Я понимаю, как работает отношение повторения, и все, но я не могу понять, как оно может избежать дубликатов, в то время как мое решение нет. Пожалуйста, объясните идею.
1 ответов
пусть C(i, j)
количество способов сделать общей сумме i
использование монет номиналов S1, ..., Sj
. Ваш код реализует следующее повторение (упорядоченные способы).
C(i, m) | i < 0 = 0
| i == 0 = 1
| i > 0 = sum_{j = 1}^m C(i - Sj, m)
связанный код реализует другое повторение (неупорядоченные способы).
C(i, j) | i < 0 = 0
| i == 0 = 1
| i > 0 && j <= 0 = 0
| i > 0 && j > 0 = C(i - Sj, j) + C(i, j - 1)
разница между двумя кодами тонкая: более или менее точно, как вложены циклы. Ваш добавляет все условия для i
до i + 1
, но связанный код добавляет j
термин для каждого i
, потом j + 1
срок для каждого i
, etc. В результате, когда связанный код, рассматривает возможность использования деноминации-Sj
монета итого i
, он неявно рассматривает только те решения, которые продолжаются с монетами номиналов S1, ..., Sj
, потому что текущая сумма для i - Sj
не включает в себя возможности, которые используют другие монеты.