递归函数构建

时间:2013-01-29 06:15:09

标签: c recursion tail-recursion backtracking

我正在尝试编写一个函数来探索数字的所有可能组合,以数组形式给出,希望找到加起来一定数量的最小数字组,并将其作为参数传递。

这是我一直在做的事情,这似乎适用于一些但不是所有情况;

我选择一个数字,从总和中减去它,并将新的总和传递给函数,数组的限制保持不变,这使我可以选择重新选择数字,
在第二次调用中,我传递了新的总和,即总和减去当前选择的数字,但我将数组缩小了一个,这意味着我不会再选择相同的数字。

然而,我已经意识到我并没有涵盖所有选择,因为无论如何我假设任何数字对解决方案都至关重要,但我不知道要通过哪些参数来覆盖第三个选项,它不是选择数字,意味着我不会从总和中减去数字,而是缩小数组的大小。

你的帮助将不胜感激,顺便说一下,我正在用C语言写作。

    int howManyCoins(int*coins,int size,int sum)
{
    return howManyCoins_aux(coins,size,sum,size-1);
}

int howManyCoins_aux(int*coins,int size, int sum,int chosen)
{
    if (sum==0)return 1;
    if (sum<0)return 0;
    if (chosen==0) return 0;
    if (coins[chosen]>sum) return 0;
    int res1=0,res2=0,best_solution=0;
    for (int i=chosen;i>=0;i--)
    {
        res1+=howManyCoins_aux(coins,size,sum-coins[i],chosen);
        res2+=howManyCoins_aux(coins,size,sum-coins[i],chosen-1);
        if(!(res1+res2)) best_solution=0;
        else if (res1==0) best_solution=res2;
        else if (res2==0) best_solution=res1;
        else best_solution=res2>res1?res1:res2;
    }
    return best_solution;
}

3 个答案:

答案 0 :(得分:0)

如果要检查所有可能的值,可以使用位数组。如果给定的数组足够短,则可以使用整数(或长整数)作为位数组。 现在,让a成为你的数组,然后为每个索引n:   如果且只有位数组的位n被设置,则[n]处于组合中。

答案 1 :(得分:0)

您可以简化您的选择:选择硬币并重新选择硬币或不选择硬币(递归将涵盖所有选项)

替换:

res1+=howManyCoins_aux(coins,size,sum-coins[i],chosen);
res2+=howManyCoins_aux(coins,size,sum-coins[i],chosen-1);

res1 = howManyCoins_aux(coins, size, sum-coins[i], chosen);
res2 = howManyCoins_aux(coins, size, sum, chosen-1);

如果你只能挑选每枚硬币中的一个:(这是change-making problem

res1 = howManyCoins_aux(coins, size, sum-coins[i], chosen-1);
res2 = howManyCoins_aux(coins, size, sum, chosen-1);

你的算法有点不清楚,我认为有很多重复。您可以摆脱for循环,并将您的功能更改为:(未经测试)

int howManyCoins_aux(int *coins, int size, int sum, int chosen, int pos)
{
  if (sum == 0) return chosen;
  if (sum < 0 || pos == size) return 9999999;
  int res1 = 9999999;
  if (coins[pos] >= sum)
    res1 = howManyCoins_aux(coins, size, sum-coins[pos], chosen+1, pos);
  int res2 = howManyCoins_aux(coins, size, sum, chosen, pos+1);
  return min(res1, res2);
}

话虽如此,递归可能不是可行的方法(即使在小型数据集上也需要很长时间)。听起来像integer programming。在链接中有一些解决方案可供选择。

答案 2 :(得分:0)

这听起来像是子集求和问题的变体。由于您只考虑正数,因此如果您保留另一个数据结构来跟踪与每个可能值相加的数字集,那么像here所述的动态编程方法可能会起作用。