算法 - 硬币改变代码错误

时间:2014-08-03 05:17:44

标签: c algorithm recursion coin-change

给定值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;
}

1 个答案:

答案 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;
}