我的输入是:
W[10] = {1, 3, 5, 7, 9, 12, 19, 22, 36, 63}
X[10] = {0};
M = 79;
我通过以下方式调用了该函数:
findSolution(0,0,177); <br>
注意:177是W数组中所有元素的总和。
void findSolution(int s, int k, int r) {
cout << "fn(" << s << " , " << k << ", " << r << " )" << endl;
X[k] = 1;
if (s + W[k] == M){
printArr(X);
}
else if (s + W[k] + W[k + 1] <= M) {
return findSolution(s + W[k], k + 1, r - W[k]);
}
if ((s + r - W[k] >= M) && (s + W[k + 1]) <= M){
X[k] = 0;
return findSolution(s, k + 1, r - W[k]);
}
}
输出:
fn(0 , 0, 177 )
fn(1 , 1, 176 )
fn(4 , 2, 173 )
fn(9 , 3, 168 )
fn(16 , 4, 161 )
fn(25 , 5, 152 )
fn(37 , 6, 140 )
fn(56 , 7, 121 )
上面给出的输出是跟踪函数调用。输出在此结束,不会继续。我的代码有什么问题。我正在尝试打印一个子集,它给出了所需的sum = 79.递归调用不会返回。
答案 0 :(得分:0)
递归调用 返回;它只是在您找到解决方案之前这样做。如果达到最后if
但失败,则会发生这种情况。 (请注意,当您调用printArr
时,看起来像您的基本情况,不必然会停止递归。)
答案 1 :(得分:0)
您的解决方案的问题在于它使用了greedy策略(即,在找到合适的候选人后,它没有&#34;回溯&#34;)
您的算法会检查三个条件:
k
- 元素添加到子集中,或者k-1
- st元素与k
- th。此策略并未用尽所有可能性:例如,可能无法用k
- st替换k+1
- 元素,但可能会在k
之前替换多个元素{1}} - 与k+1
- st并获得解决方案。你的策略是贪婪的,因为当它发现一个元素可以添加到一个集合(即s + W[k] + W[k + 1] <= M
)时,它会采用该路径,并且永远不会回头(即从该分支返回)。
您可以通过重构代码来解决此问题:
true
,否则返回false
。if (s + W[k] == M)
,并在找到解决方案时添加return true
。k
- 元素添加到集合中。如果可能,请添加它,并尝试s + W[k]
true
,请返回true
。k
- 元素,并在混合中没有k
- 元素的情况下进行第二次递归调用。使用s
。现在你的算法是穷举的,因为对于每个元素,当元素是解的一部分时,算法试图找到一个部分和,当元素不是解的一部分时(即O(2 n) )检查所有)。