我正在尝试计算向量中所有可能组合数的总和。如果组合等于给定数字,则该函数返回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;
}
正如你所看到的,我能够计算给定根点的数字总和的一个级别,但是我会陷入必须继续向上扩展的位置。似乎应该涉及调用自身的方法并递归地越来越多的分支,但我无法弄清楚如何做到这一点。
答案 0 :(得分:1)
在数学上,您可以通过将数组想象为长度为n
的二进制字符串来迭代地执行此操作。在每个索引处,它都是1
或0
。如果是1
,那么我们将其添加到总和中,如果是0
,我们会将其从总和中排除。
您所要做的就是浏览从n
到000....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
变为负数,则可以跳过该分支的其余部分。这种“修剪”技术通常比穷举迭代更快地制作这样的方法。
修剪的另一个建议是,当分支上的所有正元素(并且只有正元素)包含在目标之外时,返回不同的值。这意味着任何子集都无法到达目标。