【发布时间】:2019-11-10 05:35:26
【问题描述】:
我想知道这种回溯算法是否真的有效。
在教科书Foundations of Algorithms,第5th版中,定义如下:
算法 5.4:子集和问题的回溯算法
问题:给定n个正整数(权重)和一个正整数W, 确定总和为 W 的整数的所有组合。
输入:正整数n,排序(非降序)数组 从 1 到 n 索引的正整数 w,以及一个正整数 W.
输出:总和为 W 的所有整数组合。
void sum_of_subsets(index i, int weight, int total) { if (promising(i)) if (weight == W) cout << include[1] through include [i]; else { include[i + 1] = "yes"; // Include w[i + 1]. sum_of_subsets(i + 1, weight + w[i + 1], total - w[i + 1]); include[i + 1] = "no"; // Do not include w[i + 1]. sum_of_subsets(i + 1, weight, total - w[i + 1]); } } bool promising (index i); { return (weight + total >= W) && (weight == W || weight + w[i + 1] <= W); }按照我们通常的约定,n、w、W、 和 include 不是 输入到我们的例程中。如果这些变量是全局定义的,则 对 sum_of_subsets 的顶级调用如下:
sum_of_subsets(0, 0, total);
在第 5 章的结尾,exercise 13 问:
对子集和问题使用回溯算法(算法 5.4) 找到以下数字的所有组合,总和为 W = 52:
w1 = 2 w2 = 10 w3 = 13 w4 = 17 w5 = 22 w6 = 42
我已经实现了这个精确的算法,考虑到从 1 开始的数组,它只是不起作用......
void sos(int i, int weight, int total) {
int yes = 1;
int no = 0;
if (promising(i, weight, total)) {
if (weight == W) {
for (int j = 0; j < arraySize; j++) {
std::cout << include[j] << " ";
}
std::cout << "\n";
}
else if(i < arraySize) {
include[i+1] = yes;
sos(i + 1, weight + w[i+1], total - w[i+1]);
include[i+1] = no;
sos(i + 1, weight, total - w[i+1]);
}
}
}
int promising(int i, int weight, int total) {
return (weight + total >= W) && (weight == W || weight + w[i+1] <= W);
}
我相信问题出在这里:
sos(i + 1, weight, total - w[i+1]);
sum_of_subsets(i+1, weight, total-w[i+1]);
当你到达这条线时,你没有正确回溯。
是否有人能够识别此算法的问题或实际对其进行编码以使其工作?
【问题讨论】:
-
这不是最低可重现代码。数组
w和include是如何定义的? -
是我自己还是这太复杂了?有前途的功能看起来像代码混淆比赛的参赛者......
标签: c++ algorithm backtracking