SPOJ:加权总和

时间:2013-08-15 19:10:06

标签: algorithm dynamic-programming greedy

您获得 N个整数,A [1]到A [N] 。您必须为这些整数分配权重,使其weighted sum is maximized。权重应满足以下条件:

  1. 每个重量应为正整数。
  2. W [1] = 1
  3. 对于i,
  4. W [i]应该在[2,W [i-1] + 1]的范围内。 1
  5. 加权和定义为S = A [1] * W [1] + A [2] * W [2] + ... + A [N] * W [N]

    例如:

    n=4 , array[]={ 1 2 3 -4 } , answer = 6 when we assign { 1 2 3 2 } respective weights .
    

    因此,就我的理解和研究而言,没有Greed解决方案是可能的。我用笔在纸上制作了许多测试用例,但无法获得贪婪的策略。

    任何想法/提示/接近人。

4 个答案:

答案 0 :(得分:1)

通过将权重dp[i][j]分配给A[1..i]j等于我们可以从A[i]获得的最大加权和。显然dp[i][j] = j*A[i] + max(dp[i - 1][(j - 1)..N])。有O(N^2)个状态,每个州的重复次数为O(N),因此整体时间复杂度为O(N^3)。为了将其减少到O(N^2),我们可以注意到我们的重复出现了重大的重叠。

如果dp[i][j] = j * A[i] + max(dp[i - 1][(j - 1)..N]),那么

dp[i][j - 1] = (j - 1)*A[i] + max(dp[i - 1][(j - 2)..N]) = (j - 1)*A[i] + max(dp[i - 1][j - 2], dp[i - 1][(j - 1)..N]) = (j - 1)*A[i] + max(dp[i - 1][j - 2], dp[i][j] - j*A[i])

这意味着重复只需要O(1)来计算,总体上给你O(N ^ 2)时间。

答案 1 :(得分:0)

不是解决方案,而是一个想法: 我认为某种爬山方法可能会产生很好的效果。

我们可以观察到我们可以提出的“最差”最佳解决方案是

  

1 2 2 2 2等

也就是说,我们可以分配给不属于索引0的任何数字的最低权重是2。因此,我们可以为任何负数分配的最低权重为2

这个初始重量分布为我们提供了一个起点。

我敢打赌,我们可以不断修改我们的体重分布,使得总和永远不会减少。也就是说,我们永远不需要暂时获得长期收益。

问题是,我们的迭代策略应该是什么?因为后续权重对以前的权重有一定的依赖性,我们如何迭代?

也许你可以做一些事情,你拿第一个正数并将其增加到最高值,然后对下一个正数和下一个执行相同的操作。

之后,您可以解决序列中的第一对(负,正)数字,同时增加两个数字(如果可能)以查看最终结果是否更好。

然后你执行另一轮递增正数 之后的那个序列,然后找到 next 对(负数,正数),并重复。

答案 2 :(得分:0)

可以使用相当标准的动态编程方法在O(N³)时间内解决这个问题。设V(k,u)表示当Wₖ₋1具有值u时可以使用元素k ... N得到的最佳值。观察到V(k,u)是g·Aₖ+ V(k-1,g)的最大值,因为g的范围是2到u + 1,并且V(N,u)是(u + 1)·如果A N 为正,则 N ,否则为2·A N

请注意,在任何V(k,u)计算中u最多为k,因此(k,u)有N *(N-1)/ 2个可能的值,因此概述的方法使用O(N²) )空间和O(N³)时间。

答案 3 :(得分:0)

这是一个小小的洞察力,可以让您或其他人提出一个非常快速的解决方案。请注意,对于最佳解决方案,您可以安全地假设在每个步骤中,您将重量从前一个重量增加+1,或者您将重量一直减少到最小值2.要看到这一点,假设您有违反财产的最佳解决方案。然后你有一些重量> 2在某个位置i-1,下一个重量也是> 2位于i但不是增加。现在考虑从位置i开始的最优解中的最大长度弱增加子序列(弱增加意味着在子序列的每个步骤中,权重不减小)。通过假设,具有该子序列的最优解不比同一解更差,除了从其所有权重中减去1的子序列。但这意味着将子序列中的所有权重增加1也不会使最优解更糟。因此,对于最佳解决方案,在每个步骤中,您可以安全地假设您将重量增加1或将重量设置为最小值2.