SUM完全使用K元素解决方案

时间:2015-08-04 07:34:42

标签: algorithm recursion dynamic-programming recurrence

问题:在具有N个数字的给定数组上,找到大小为M(正好是M个元素)的子集,其等于SUM。

我正在寻找针对此问题的动态编程(DP)解决方案。基本上是要了解矩阵填充方法。我写了下面的程序,但没有添加记忆,因为我仍然想知道如何做到这一点。

    #include <stdio.h>
    #define SIZE(a) sizeof(a)/sizeof(a[0])
    int binary[100];
    int a[] = {1, 2, 5, 5, 100};

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

    void subset_sum(int target, int i, int sum, int *a, int size, int K) {
            if (sum == target && !K) {
                    show(binary, size);
            } else if (sum < target && i < size) {
                    binary[i] = 1;
                    foo(target, i + 1, sum + a[i], a, size, K-1);
                    binary[i] = 0;
                    foo(target, i + 1, sum, a, size, K);
            }
    }

    int main() {
            int target = 10;
            int K = 2;
            subset_sum(target, 0, 0, a, SIZE(a), K);
    }

下面的重复解决方案是否有意义?

让DP [SUM] [j] [k]与从0到j元素中挑选的K个元素完全相加。

 DP[i][j][k] = DP[i][j-1][k] || DP[i-a[j]][j-1][k-1] { input array a[0....j] }

基本案例是:

DP[0][0][0] = DP[0][j][0] = DP[0][0][k] = 1
DP[i][0][0] = DP[i][j][0] = 0

这意味着我们可以考虑这个元素(DP [ia [j]] [j-1] [k-1])或者我们不考虑当前元素(DP [i] [j-1] ] [K])。如果我们考虑当前元素,k减少1,这减少了需要考虑的元素,当不考虑当前元素时也是如此,即K不减少1。

2 个答案:

答案 0 :(得分:3)

你的解决方案看起来对我来说。

现在,您基本上回溯所有可能性并打印每个解决方案。如果您只需要一个解决方案,则可以添加在找到一个解决方案时设置的标志,并在继续递归调用之前进行检查。

对于memoization,你应该首先摆脱binary数组,之后你可以这样做:

int memo[NUM_ELEMENTS][MAX_SUM][MAX_K]; 
bool subset_sum(int target, int i, int sum, int *a, int size, int K) {
            if (sum == target && !K) {
                    memo[i][sum][K] = true;
                    return memo[i][sum][K];
            } else if (sum < target && i < size) {
                    if (memo[i][sum][K] != -1)
                        return memo[i][sum][K];


                    memo[i][sum][K] = foo(target, i + 1, sum + a[i], a, size, K-1) || 
                                      foo(target, i + 1, sum, a, size, K);

                    return memo[i][sum][K]
            }

            return false;
    }

然后,看看memo[_all indexes_][target][K]。如果是这样,则至少存在一种解决方案。您可以存储附加信息以获取下一个解决方案,或者您可以使用ifound_index - 10进行迭代,并检查您i memo[i][sum - a[i]][K - 1] == true memo }。然后递归,等等。这将允许您仅使用Server srv = new Server(); var dependencyWalker = new DependencyWalker(srv); var dependencyTree = dependencyWalker.DiscoverDependencies(new Urn[] { srv.Databases["myDB"].Tables["Resource"].Urn }, DependencyType.Parents); var dependencyCollection = dependencyWalker.WalkDependencies(dependencyTree); 数组重建解决方案。

答案 1 :(得分:0)

据我了解,如果只需检查输入的可行性,可以用二维状态空间解决问题

bool[][] IsFeasible = new bool[n][k]

其中IsFeasible[i][j]true当且仅当有1i的元素的子集时,每个<{1}}总和为j < / p>

1 <= i <= n
1 <= j <= k

并且对于此状态空间,递归关系

IsFeasible[i][j] = IsFeasible[i-1][k-a[i]] || IsFeasible[i-1][k]
可以使用

,其中or-operator ||的左侧对应于选择i项,右侧对应 not 选择i项。实际的项目选择可以通过回溯或评估期间保存的辅助信息来获得。