我已经查看了这里的回溯问题,但没有一个显示从详尽的递归方法到子集求和问题转换为使用回溯的问题。
我们从CanMakeSum函数开始,该函数接受一个集合并确定它是否可以产生总和。
代码与此问题的问题完全相同:Recursion: Understanding (subset-sum) inclusion/exclusion pattern。
现在需要重写这段代码:
在每一步,我需要选择其中一个剩余元素添加到子集并从那里重复。这就是为什么下面的代码采用不同的方法,并且是上述代码中的REWRITE(这是一种不同的方法)。
必须更改功能以打印所有与目标相加的成员。
更改函数以报告所有可能子集的计数。
这是我到目前为止所做的,但它不起作用。我对这个逻辑感到困惑。
int main () {
while (true) {
if (response == 0) break;
cout << "Please type in integers. When finished, press 0: ";
response = GetInteger();
sumvector.add(response);
}
cout << "Please enter a target sum: ";
int target = GetInteger();
if (CanMakeSum(sumvector, target)) {
cout << "Yes, a sum exists in this vector." << endl;
} else {
cout << "No, a sum does not exist in this vector." << endl;
}
return 0;
}
bool CanMakeSum(Vector<int> & nums, int targetSum) {
if (nums.isEmpty()) {
return targetSum == 0;
} else {
for (int i = 0; i < nums.size(); i++) {
int element = nums[i];
Vector<int> rest;
rest.add(element);
nums.removeAt(i);
if (CanMakeSum(rest, targetSum - element)) {
cout << "These numbers, in rest, make up the targetSum." << endl;
return true;
}
}
}
return false;
}
非常感谢任何帮助。
答案 0 :(得分:0)
您的代码中似乎存在错误。对于每个递归调用,rest
中只有一个元素,即element
。我相信您希望在没有 rest
的情况下将nums
初始化为整个输入element
。此外,你的基础案例似乎毫无意义;如果只有非负参数有效,并且返回值应为targetSum
,则递归应在true
为零时结束。在循环中,如果无法选择合适的项目,则应返回false
。
必须使用辅助数据结构维护子集的实际选择,例如Vector<int>
,它可以是全局的,也可以通过引用传递到每个递归调用中,并用所选项填充。在基本情况下,必须打印其内容,但在每次递归调用之后,必须再次删除相应的所选项。然后该算法将详尽地枚举每个合适的子集。
整体方法可能如下所示。假设我们有一些全局Vector<int> partial_solution
,最初是空的
bool CanMakeSum(Vector<int> & nums, int targetSum) {
if ( 0 == targetSum ){
// todo: output partial_solution
return true;
} else {
for (int i = 0; i < nums.size(); i++) {
int element = nums[i];
if ( element >= targetSum ){ // check whether element can actually be chosen
Vector<int> rest;
// todo: initialize rest to contain nums without element
// todo: add element to partial_solution
if (CanMakeSum(rest, targetSum - element)) {
return true;
}
// todo: remove element from partial_solution
}
}
return false;
}