求解动态规划练习的算法(背包式)

标签 algorithm geometry dynamic-programming knapsack-problem

这里是挑战:输入是一个包含 N 个整数的数组 X(N 的范围是 0 到 10'000,X[i] 的范围是 -100 到 100)。目标是从集合 {-1; 中找到一个由 N 个整数组成的序列 D。 1}这样

S = | sum_i (X[i] * D[i]) |

被最小化。如果我们输出整数 S(不需要明确地找到使 S 最小的序列 D),问题就解决了。

我目前的研究:

  1. 计算

    M = sum_i | X[i] |

并解决以 M/2 为背包容量和 X 为项目列表的 0-1 背包问题。它给出了正确的答案,但复杂度太高。

  1. 对于范围为 0 到 N 的整数 n 和范围为 -100 到 100 的整数 r,定义

    s(n, r) = 1 如果存在长度为 n 的整数序列 D 来自集合 {-1; 1} 这样 r = | sum_{i = 0 到 n} (X[i] * D[i]} |

    s(n, r) = 0 否则。

则s有如下性质:

s(n, r) = s(n - 1, r - X[n]) || s(n - 1, r + X[n])

翻译成英语,如果前 n 个项目可以到达 r,那么前 (n - 1) 个项目可以到达 r - X[n] 或 r + X[n]。

根据这个属性,可以很容易地为给定范围内的任何 r 计算 s(N, r)。 当 X 按降序排序时,它提供了更多返回正确答案的机会,但在某些情况下它仍然不正确。也许可以通过为 r 提供更大的范围来纠正它,但如果有可接受的范围,我现在还不知道。

  1. 几何/线性代数方法:将所有可能的序列 D 视为欧几里得空间 R^k (k >= N) 中的向量,并在 R^k 的正交基中划分所有可能 D 的集合,然后将 X 写入每个新基地。但我对它能奏效的希望不大......

提示:

  1. N 的范围(X 的大小)远大于每个 X[i] 的范围。因此序列 X 将有重复项。

最佳答案

诀窍在于 D[i] 来自 X[i] 的相反序数排列。这通过确保最小因子乘以最大因子来最小化总和;并且每个较小的因素都与每个较大的因素归纳配对。从技术上讲,这是因为欧几里得定理。所以总和的每个乘积都有最小的质因数集。人们可能会发现 X 与冒泡排序的序数排列,它在基数为 N 的一组索引 I 上并行运行。理解背包问题的关键是更高维度的旋转对应于向量空间中的转置。

关于求解动态规划练习的算法(背包式),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31424578/

相关文章:

algorithm - 最大堆化二叉树

algorithm - 在字符串数组中查找字符串的最快算法?

python - 使用向量叉积隐藏 3D 人脸

python - 解决硬币上的动态规划问题

arrays - VBA - 匹配2个排序字符串数组,其中某些元素不匹配 - 优化

algorithm - 树中的大 O(h) 与大 O(logn)

math - 电子围栏的局部最优

android - 在圆圈下方绘制文字

algorithm - 杆切割的变体

c++ - 这个 DP 解决方案是如何处理的?