Основная идея - для каждой монеты j, значение [j] <= i (то есть сумма), мы смотрим на минимальное количество монет, найденных для i-значения [j] (скажем, m) сумма (ранее найденная),Если m + 1 меньше минимального количества монет, уже найденных для текущей суммы i, то мы обновляем количество монет в массиве. </p>
Для ex-sum = 11 n = 3 и значения [] = {1,3,5}
Ниже приводится результат, который мы получаем
i- 1 mins[i] - 1
i- 2 mins[i] - 2
i- 3 mins[i] - 3
i- 3 mins[i] - 1
i- 4 mins[i] - 2
i- 5 mins[i] - 3
i- 5 mins[i] - 1
i- 6 mins[i] - 2
i- 7 mins[i] - 3
i- 8 mins[i] - 4
i- 8 mins[i] - 2
i- 9 mins[i] - 3
i- 10 mins[i] - 4
i- 10 mins[i] - 2
i- 11 mins[i] - 3
Как мы можем наблюдать для суммы i = 3, 5, 8 и 10, мы улучшаем наш предыдущий минимум следующими способами -
sum = 3, 3 (1+1+1) coins of 1 to one 3 value coin
sum = 5, 3 (3+1+1) coins to one 5 value coin
sum = 8, 4 (5+1+1+1) coins to 2 (5+3) coins
sum = 10, 4 (5+3+1+1) coins to 2 (5+5) coins.
Таким образом, для суммы = 11 мы получим ответ как 3 (5 + 5 + 1).
Вот код на C. Он похож на псевдокод, указанный на странице topcoder, ссылка на которую приведена в одном из ответов выше.
int findDPMinCoins(int value[], int num, int sum)
{
int mins[sum+1];
int i,j;
for(i=1;i<=sum;i++)
mins[i] = INT_MAX;
mins[0] = 0;
for(i=1;i<=sum;i++)
{
for(j=0;j<num;j++)
{
if(value[j]<=i && ((mins[i-value[j]]+1) < mins[i]))
{
mins[i] = mins[i-value[j]] + 1;
printf("i- %d mins[i] - %d\n",i,mins[i]);
}
}
}
return mins[sum];
}