【问题标题】:Modification to subsetsum algorithm by pisingerpisger 对子集算法的修改
【发布时间】:2014-06-29 06:28:59
【问题描述】:

我正在查看 pisinger 的算法,详见此处

Fast solution to Subset sum algorithm by Pisinger

在维基百科上http://en.wikipedia.org/wiki/Subset_sum_problem

For the case that each xi is positive and bounded by a fixed constant C, Pisinger found a linear time algorithm having time complexity O(NC).[3] (Note that this is for the version of the problem where the target sum is not necessarily zero, otherwise the problem would be trivial.)

他的方法似乎有两个限制。第一个特别表示任何输入中的所有值都必须是<= C

在我看来,仅凭这个约束,这不是一个可以解决原始子集和问题的算法(没有限制)。

但假设C=1000000 为例。然后在我们甚至在输入列表上运行算法之前。我们不能只将每个元素除以某个数字d(也将目标总和除以d),这样输入列表中的每个数字都是<= C。 当算法返回某个子集s 时,我们只需将s 中的每个元素乘以d。我们将拥有真正的子集。

通过观察,感觉不值得一提的是我们需要C 约束。或者至少说输入可以改变 W.L.O.G (不失一般性)。所以无论输入如何,我们仍然可以解决同样的问题。换句话说,这种约束并没有使问题变得更加困难。所以实际上他的算法唯一的限制是它只能处理数字>=0

我说的对吗?

谢谢

【问题讨论】:

  • 在维基百科文章的开头它说:“问题是这样的:给定一组(或多组)整数”。如果将数字除以常数“d”,它们可能不会保持整数。
  • 我不知道算法,但从你写的内容来看,我猜它利用了每个元素只有有限多种可能性的事实。如果除以某个常数,这个可能性的数量不会改变。

标签: algorithm complexity-theory np


【解决方案1】:

adrian.budau 说的是对的。

在多项式解中, 在你说的除法之后,数组的每个值都应该保持为整数。 否则 DP 解决方案不再起作用,因为项目值被用作 DP 数组中的索引。

以下是我的子集和问题的多项式 (DP) 解决方案 (C=ELEMENT_MAX_VALUE)

bool subsetsum_dp(VI& v, int sum)
{
    const int MAX_ELEMENT = 100;
    const int MAX_ELEMENT_VALUE = 1000;
    static int dp[MAX_ELEMENT+1][MAX_ELEMENT*MAX_ELEMENT_VALUE + 1]; memset(dp, -1, sizeof(dp));

    int n = S(v);
    dp[0][0] = 1, dp[0][v[0]] = 1;//include, excluse the value
    FOR(i, 1, n)
    {
        REP(j, MAX_ELEMENT*MAX_ELEMENT_VALUE + 1)
        {
            if (dp[i-1][j] != -1) dp[i][j] = 1, dp[i][j + v[i]] = 1;//include, excluse the value
        }
    } 
    if (dp[n-1][sum] == 1) return true;
    return false;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-19
    • 2013-11-04
    • 1970-01-01
    • 2017-11-09
    相关资源
    最近更新 更多