0

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

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

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

但是,我意识到我并没有涵盖所有选择,因为无论如何我假设任何数字对于解决方案都是至关重要的,但我不知道要传递哪些参数才能涵盖第三个选项,这不是选择数字,这意味着我不会从 sum 中减去,并缩小数组的大小。

您的帮助将不胜感激,顺便说一句,我正在用 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;
}
4

3 回答 3

0

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

于 2013-01-29T06:36:45.317 回答
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);

如果每个硬币只能选1个:(这是找零问题

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);
}

话虽如此,递归可能不是要走的路(即使在小型数据集上也需要很长时间)。听起来像整数规划。有几个选项可以在链接中解决它。

于 2013-01-29T06:55:57.910 回答
0

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

于 2013-01-30T03:35:28.173 回答