【问题标题】:Finding subset sum recursively producing incorrect output递归查找子集总和产生不正确的输出
【发布时间】:2015-06-27 15:29:51
【问题描述】:

按照this method (pdf) 实现递归解决方案,但我认为它有问题。我已经按照 pdf 文件中的描述完全实现了它。

下面代码的输出是错误的。它显示了目标位置。目标数组包含应相加以获得总和的数字的位表示。

binary[i] = 1 放在else if 条件中可以解决问题,但没有意义。

是否有可能澄清什么是正确的解决方案?

#define SIZE(a) sizeof(a)/sizeof(a[0])
int binary[100];
void foo(int target, int i, int sum, int *a, int size) {
    binary[i] = 1;
    if (target == sum+a[i]) {
        int j;
        for (j=0;j<size;j++)
            printf("%d\n", binary[j]);
        return;
    } else if ((i+1 < size) && (sum + a[i] < target)) {
        foo(target, i+1, sum + a[i], a, size);
    }
    if ((i+1 < size) && (sum +a[i+1] <= target)) {
        binary[i] = 0;
        foo(target, i+1, sum, a, size);
    }
}

int main()
{
    int i, target =10,a[] = {1, 2, 3, 5, 100};
    foo(target, 0, 0, a, SIZE(a));
}

当前输出:0 1 1 1 1

预期输出:0 1 1 1 0

【问题讨论】:

  • 哪种语言? C? C++?请相应标记
  • 请添加当前输出,以及您期望的正确输出。也尽量让自己更容易,不要使用tia,而是使用有意义的变量名。

标签: c algorithm recursion subset-sum


【解决方案1】:
#include <stdio.h>

#define SIZE(a) sizeof(a)/sizeof(a[0])
int binary[100];

void show(int* p, int size) {
    int j;
    for (j = 0; j < size; j++)
        printf("%d\n", p[j]);
}

void foo(int target, int i, int sum, int *a, int size) {
    if (sum == target) {
        // solution found
        show(binary, size);
    } else if (sum < target && i < size) {
        // try both branches
        // 1. current value used
        binary[i] = 1;
        foo(target, i + 1, sum + a[i], a, size);
        // 2. current value skipped
        binary[i] = 0;
        foo(target, i + 1, sum, a, size);
    } else {
        // no solution on this path
    }
}

int main() {
    int target = 10;
    int a[] = {1, 2, 3, 5, 100};
    foo(target, 0, 0, a, SIZE(a));
}

解释:

  • 我们只讨论isumbinary,因为从该算法的角度来看,其他一切都是不变的。
  • 我们的目标是从a 中选择总和等于target 的单个元素。当我们遇到这种情况时,我们就完成了,我们唯一的工作就是show 解决方案。
  • 只有当我们当前的sum 仍然低于target,并且我们还没有到达a 的末尾时,算法才能继续进行。
  • 总是有两种可能性:使用当前元素或跳过它。两者都是递归调查的。
  • 该过程必须在binary 的适当位置保留零,否则会在backtracking 的各个级别提供误导性结果。出于这个原因,首先研究了 use 分支。

【讨论】:

  • @newbie_old 你是对的。我已经确定了我的答案。我不得不将条件i + 1 &lt; size 更改为i &lt; size,并交换“已使用”和“跳过”分支,以便在binary 数组中保留零,以获取backtracking 可能找到的其他解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-05
  • 2012-02-19
  • 1970-01-01
  • 1970-01-01
  • 2020-04-06
  • 2020-01-26
相关资源
最近更新 更多