给定值N,如果我们想要改变N美分,并且我们每个S = {S1,S2,..,Sm}值的硬币都有无限供应,我们可以通过多少方式进行更改?硬币的顺序无关紧要。
我写了下面的代码,但它总是比实际答案少一个。我想知道这是否是编写解决方案的正确方法?
#include <stdio.h>
int ways=0;
int remember[100] = {0};
void foo(int coin_denomination[], int size, int sum)
{
int i;
printf("%d\n", sum);
if (sum==0) {
ways++;
return;
}
if (remember[sum]==1)
return;
remember[sum] = 1;
if (sum < 0)
return;
for(i=0;i<size;i++)
foo(coin_denomination, size, sum-coin_denomination[i]);
}
int main()
{
int coin_denomination[] = {1, 2, 3};
int sum = 5;
foo(coin_denomination, sizeof(coin_denomination)/sizeof(coin_denomination[0]), sum);
printf("%d\n", ways);
return 0;
}
答案 0 :(得分:2)
您需要对foo
方法进行一些更改。您的问题是,使用变量remember
,您不计算某些解决方案。变量remember
的目标不正确,您使用的是多次未处理相同的硬币收藏,但您只保存硬币收藏的总和并且可以使用多个硬币集合获得总和(例如:1 1 1
具有与1 2
相同的总和,当您选择第二个时,remember[3]
将为1而不是通过此点,缺少解决方案1 2 2
)
需要不重复coin collection
的其他方式,在这种情况下,添加一个参数来表示正在处理的coin_denomination
的索引,并且只允许处理之后的硬币,问题就解决了。< / p>
代码(使用GCC 4.9.0测试):
#include <stdio.h>
int ways=0;
void foo(int coin_denomination[], int size, int sum, int coin_idx = 0)
{
if (sum < 0)
return;
int i;
printf("%d\n", sum);
if (sum==0) {
ways++;
return;
}
for(i=coin_idx;i<size;i++)
foo(coin_denomination, size, sum-coin_denomination[i], i);
}
int main()
{
int coin_denomination[] = {1, 2, 3};
int sum = 5;
foo(coin_denomination, sizeof(coin_denomination)/sizeof(coin_denomination[0]), sum);
printf("%d\n", ways);
return 0;
}