建议的基本子句有问题,因为有了它,你也可以将s[n,0]作为初始值。
对子集和的递归公式更好的停止子句是s[i,xi] = true。这个想法很简单,集合{x1,x2,...,xi} 包含一个子集,总和为xi - 它是子集{xi}。递归将稍后处理其余部分,如果有一个子集总和为 0,它会找到它。
根据这种方法,基本子句是:
s[i,xi] = true (for each i)
s[0,j] = false (for each j)
而递归公式为:
s[i,j] = s[i-1,j] OR s[i-1,j-xi]
要获取子集中实际存在哪些元素,您需要遵循使用动态规划构建的矩阵。 “遵循”矩阵所做的选择,并坚持一条产生 true 的路径,直到找到“停止子句”(s == xi)
可以递归描述为:
getSubset(i,s):
if s[i-1,s]: //there is a solution without choosing xi
return getSubset(i-1, s)
if (xi == s): //true base clause
l <- new list
l.append(xi)
return l
if s[i -1, s-xi]: //there is a solution when choosing xi
l <- getSubset(i-1,s-xi)
l.append(xi)
return l
很像(确保你明白为什么):How to find which elements are in the bag, using Knapsack Algorithm [and not only the bag's value]?