The problem of determining optimal representation in a coin system, in general, is weakly NP-hard. Probably, for all contemporary coin systems in the World greedy algorithm works fine. Most often contemporary coin systems use so-called binary-decimal pattern 1-2-5. But your example has 25 cents which require a closer look.
But first, let's prove that 1-2-5 pattern amenable for the greedy algorithm. Observe that their LCM is 10, this means that we need to check only numbers in [1..9]
.
1 = 1,0,0 4 = 0,2,0 7 = 0,1,1
2 = 0,1,0 5 = 0,0,1 8 = 1,1,1
3 = 1,1,0 6 = 1,0,1 9 = 0,2,1
So, this pattern is greedy. Let's now turn our attention to the first six denominations 50, 25, 10, 5, 2, 1. Here we have the same LCM - 50. I wrote a program to check this:
#include <iostream>
#include <array>
#include <iomanip>
#include <algorithm>
#include <numeric>
#include <iterator>
bool IsOptimal(const int sum, const int numberOfCoins, std::array<int, 6>::const_iterator begin, std::array<int, 6>::const_iterator end) {
if (sum < 0 || numberOfCoins == 0) return true;
for (auto it = begin; it < end; ++it) {
const int nextSum = sum - *it;
if (nextSum == 0) return numberOfCoins == 1;
if (!IsOptimal(nextSum, numberOfCoins - 1, it, end))
return false;
}
return true;
}
int main() {
const std::array<int, 6> kDenoms = { 1,2,5,10,25,50 };
for (int i = 1; i < 50; ++i) {
std::array<int, 6> change = { 0 };
int sum = 0;
while (sum != i) {
auto it = std::upper_bound(kDenoms.cbegin(), kDenoms.cend(), i - sum);
++change[--it - kDenoms.cbegin()];
sum += *it;
}
const bool isOptimal = IsOptimal(sum, std::accumulate(change.cbegin(), change.cend(), 0), kDenoms.cbegin(), kDenoms.cend());
std::cout << std::setw(2) << i << ": ";
std::copy(change.cbegin(), change.cend() - 1, std::ostream_iterator<int>(std::cout, ","));
std::cout << change.back() << " " << std::boolalpha << isOptimal << std::endl;
}
return 0;
}
So, basically, what do we know? We know that all quantities less than 50 we can attack with the greedy algorithm to get its optimal solution.
Observe, that all denominations above 50 are divisible by 50, so they will not interfere with 50, 25, 10, 5, 2, 1. We also proved that the greedy algorithm works for pattern 1-2-5, so the whole set of denominations amenable for the greedy algorithm.