对向量中的所有组合求和

时间:2014-02-22 20:53:12

标签: c++

我正在尝试计算向量中所有可能组合数的总和。如果组合等于给定数字,则该函数返回false。如果没有组合等于该数字,则数组将打印该数字并返回true。

这就是我所拥有的:

bool t(vector<int>vi, int num){
  for(int i = 0; i < vi.size(); i++) {
    int sum=vi[i];
    for(int j = i+1; j < d.size(); j++) {
      if(sum + vi[j] == num) return false;
    }
  }
  cout<< num << endl;
  return true;
}

正如你所看到的,我能够计算给定根点的数字总和的一个级别,但是我会陷入必须继续向上扩展的位置。似乎应该涉及调用自身的方法并递归地越来越多的分支,但我无法弄清楚如何做到这一点。

2 个答案:

答案 0 :(得分:1)

在数学上,您可以通过将数组想象为长度为n的二进制字符串来迭代地执行此操作。在每个索引处,它都是10。如果是1,那么我们将其添加到总和中,如果是0,我们会将其从总和中排除。

您所要做的就是浏览从n000....000的每个可能长度111....111二进制字符串,并根据激活的索引求和。

在遍历所有可能的二进制字符串方面,您可以拥有一个大小为n的数组,该数组以设置为0的所有索引开头。然后你只需循环直到它成为一个所有索引都设置为1的数组。循环的每次迭代都要将1添加到索引n - 1的位。如果该位为1,则将其设置为0并继续将1添加到位置n - 2的位,依此类推(进行二进制加法)。

答案 1 :(得分:1)

递归是解决此问题的绝佳方法。

bool t_helper(vector<int>::const_iterator it, vector<int>::const_iterator end, int sum_left)
{
    if (sum_left == 0) return false;
    if (it == end) return true;
    return t_helper(it+1, end, sum_left - *it) && t_helper(it+1, end, sum_left);
}

bool t(const vector<int>& vi, int num)
{
    bool result = t_helper(vi.begin(), vi.end(), num);
    if (result) cout << num << endl;
    return result;
}

如果你知道额外的东西,你可以提前退出。例如,如果vi的元素为非负数,那么如果sum_left变为负数,则可以跳过该分支的其余部分。这种“修剪”技术通常比穷举迭代更快地制作这样的方法。

修剪的另一个建议是,当分支上的所有正元素(并且只有正元素)包含在目标之外时,返回不同的值。这意味着任何子集都无法到达目标。