问题:在具有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。
答案 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]
。如果是这样,则至少存在一种解决方案。您可以存储附加信息以获取下一个解决方案,或者您可以使用i
从found_index - 1
到0
进行迭代,并检查您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
当且仅当有1
到i
的元素的子集时,每个<{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
项。实际的项目选择可以通过回溯或评估期间保存的辅助信息来获得。