【发布时间】:2015-12-16 19:24:50
【问题描述】:
我的作业包括一个动态编程问题:
给定两个自然整数数组(a1,a2,...,an 和 b1,b2,...,bn) 这样所有的都小于n^2,并且还给出了一个数字B 小于 n^3。
如果存在数组(c1,c2,...,cn),你需要判断:
对于每个 1
*此算法必须使用动态规划编写。
*另外,我们需要改变什么来准确地得到数组 c 给我们 Sum(c) = B
看待问题的另一种方式是说 c 等于 a 的子集,而它的补子集来自 b。
这是我为解决这个问题而编写的递归伪代码:
W(a,b,i, N)
if i==-1
if N==0 return true;
else return false;
return W(a,b,i-1,N-a[i]) || W(a,b,i-1,N-b[i]);
T(n) = 2^n
在这里,要返回最佳路径,只需将其存储在树中,然后从(好的)端遍历到开始
我怎样才能用动态编程来写这个?这甚至会帮助运行时间吗?因为递归解具有独立的结果。
*我在谷歌上搜索了这个问题,除了“子集和问题”之外什么也没找到。
【问题讨论】:
-
嗯,我认为您非常接近动态规划解决方案。只需要在递归方法中添加一个
dp表,就完成了。关于时间复杂度,在这种情况下,它将等于您的dp表的大小。 -
我不明白(逻辑上)表格表示如何在这里提供帮助。我们有 2^n 个调用,我最好将其表示为一棵树。它将如何运作?
-
这是伪装的正常子集和。考虑一个新数组
d[i] = a[i] - b[i]和一个新数字g = n - sum(b)。解决subset-sum(d,g),你就有了原始问题的解决方案。 -
@Amit 您需要阅读有关动态编程的更多信息。基本上,dp 就像一个缓存层一样工作,每当您遇到之前计算的状态时,您会立即返回结果,而无需进行任何进一步的步骤/方法调用。因此,方法调用的数量受状态数量的限制。
-
@Amit你的理解不正确,比如从N = 10开始,a = {1,2,3}, b = {2,3,2}。经过两个步骤,您可以通过
a3 + a2或b3 + b2两种方式从状态 (N = 10, 2) 移动到状态 (N = 5, 0)。所以,没有dp,你会重复调用函数(a, b, 0, 5)两次。
标签: algorithm subset subset-sum