【问题标题】:How to find N points on an infinite axis so that sum of distances from M points to its nearest N is smallest?如何在无限轴上找到 N 个点,以使 M 点到其最近的 N 的距离之和最小?
【发布时间】:2019-11-28 11:04:56
【问题描述】:

考虑在一条道路上有 N 栋房屋。我有 M 个灯杆。鉴于 M

经过一番研究,我知道我必须使用动态编程来解决这个问题。但我不知道如何解决这个问题。

【问题讨论】:

  • 有一个相当简单的迭代算法可以收敛到一个局部最小值。不能保证这个最小值是全局的。您对这种解决方案感兴趣吗?

标签: c++ algorithm data-structures dynamic-programming


【解决方案1】:

这是一个带有搜索空间O(n^2 * m) 的简单动态程序。也许其他人知道另一个加速?从代码中的函数f 中应该可以清楚地看到重复。

JavaScript 代码:

// We can calculate these in O(1)
// by using our prefixes (ps) and
// the formula for a subarray, (j, i),
// reaching for a pole at i:
//
// ps[i] - ps[j-1] - (A[i] - A[j-1]) * j
//
// Examples:
// A:  [1,2,5,10]
// ps: [0,1,7,22]
// (2, 3) =>
//   22 - 1 - (10 - 2) * 2
//   = 5
//   = 10-5
// (1, 3) =>
//   22 - 0 - (10 - 1) * 1
//   = 13
//   = 10-5 + 10-2
function sumParts(A, j, i, isAssigned){
  let result = 0
  for (let k=j; k<=i; k++){
    if (isAssigned)
      result += Math.min(A[k] - A[j], A[i] - A[k])
    else
      result += A[k] - A[j]
  }
  return result
}

function f(A, ps, i, m, isAssigned){
  if (m == 1 && isAssigned)
    return ps[i]
    
  const start = m - (isAssigned ? 2 : 1)
  const _m = m - (isAssigned ? 1 : 0)
  let result = Infinity
    
  for (let j=start; j<i; j++)
    result = Math.min(
      result,
      sumParts(A, j, i, isAssigned)
        + f(A, ps, j, _m, true)
    )
  
  return result
}

var A = [1, 2, 5, 10]
var m = 2

var ps = [0]
for (let i=1; i<A.length; i++)
  ps[i] = ps[i-1] + (A[i] - A[i-1]) * i

var result = Math.min(
  f(A, ps, A.length - 1, m, true),
  f(A, ps, A.length - 1, m, false))

console.log(`A:  ${ JSON.stringify(A) }`)
console.log(`ps: ${ JSON.stringify(ps) }`)
console.log(`m:  ${ m }`)
console.log(`Result: ${ result }`)

【讨论】:

  • 这段代码可以工作,但你能解释一下这里发生了什么吗? ps[] 数组的重要性是什么?
  • @KamalPancholi ps 变量是一种特殊的前缀总和,它显示从索引 0 到 i 的元素的所有距离的总和。在这段代码中,它只用于if (m == 1 &amp;&amp; isAssigned)返回从开始到i的所有距离之和,但我在cmets中解释了我们如何也可以使用它来将sumParts中的循环转换为单个右侧有一个极点的子阵列的所有距离之和的公式(我们需要第二个,当极点在左侧时,颠倒ps)。
  • @KamalPancholi 如果分配了i,但是,我们需要使用二分搜索或有一个预先计算的表来找到点p,我们将子数组分割成距离pi,从 p-1j,因为每个房子都与靠近它的极点相关。
【解决方案2】:

我给你盖好了芽。我会先写来解释动态规划算法,如果你不会编码,请告诉我。

A-> 包含点的数组,因此 A[i]-A[i-1] 将是 A[i] 和 A[i-1] 之间的距离。 A[0] 是第一个点。当您进行自上而下的记忆时,您将不得不处理想要在当前房屋放置灯杆或想要将其放置在较低索引处的情况。如果您现在放置它,您将使用更少的灯杆进行递归,并计算与以前房屋的距离总和。当您没有任何灯杆或完成所有房屋时,您可以处理底座。

【讨论】:

  • 如果您不提供任何伪代码或常规代码,请至少将重现形式化。通过“形式化”,我的意思是写一个数学公式来表达递归的一般情况。事实上,这个答案还不清楚。
猜你喜欢
  • 2013-12-09
  • 1970-01-01
  • 2016-02-19
  • 1970-01-01
  • 1970-01-01
  • 2020-02-29
  • 1970-01-01
  • 2015-07-01
  • 2020-09-24
相关资源
最近更新 更多