** Задача за монети - минимален брой [Coin problem, AL p. 65]
Дадени са монети със стойности c1, c2, ...,
ck и целева сума n. Задачата е да се направи тази сума
с минимален брой монети.
Пример: Дадени са три вида монети със стойности 1, 3 и 4.
solve(0) = 0
solve(1) = 1
solve(2) = 2
solve(3) = 1
solve(4) = 1
solve(5) = 2
solve(6) = 2
solve(7) = 2
solve(8) = 2
solve(9) = 3
solve(10) = 3
Рекурсивна формула за примера:
solve(x) = min(solve(x−1) + 1, solve(x−3) + 1, solve(x−4) + 1)
solve(10) = solve(7) + 1 = solve(4) + 2 = solve(0) + 3 = 3.
Обща рекурсивна формула:
solve(0) = 0, solve(x) = min {solve(x - ci) + 1, i = 1,
2,..., k}
int solve(int x)
{
if (x == 0) return 0;
int best = INF;
for (int i = 0; i < k; i++)
if (x - c[i] >= 0)
best = min(best, solve(x - c[i]) + 1);
return best;
}
Със запомняне на пресметнатите стойности (memorization):
int solve(int x)
{
if (x == 0) return 0;
if (value[x] >= 0) return
value[x];
int best = INF;
for (int i = 0; i < k; i++)
if (x - c[i]
>= 0) best = min(best, solve(x - c[i]) + 1);
value[x] = best;
return best;
}
Итеративен вариант:
value[0] = 0;
for (int x = 1; x <= n; x++)
{
value[x] = INF;
for (int i = 0; i < k; i++)
if (x - c[i]
>= 0) value[x] = min(value[x], value[x - c[i]] + 1);
}
Това решение получава с колко монети може да се направи сумата. С
кои монети е това решение може да се намери със следната
модификация:
int first[N];
value[0] = 0;
for (int x = 1; x <= n; x++)
{
value[x] = INF;
for (int i = 0; i < k; i++)
if (x-c >= 0
&& value[x-c]+1 < value[x])
{
value[x] =
value[x-c[i]]+1;
first[x] = c[i];
}
}
while (n > 0)
{
cout << first[n] <<
"\n";
n -= first[n];
}