如何在无限轴上找到N个点,以使M个点到最接近的N个点的距离之和最小?

时间:2019-07-19 12:38:57

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

考虑在一条道路上有N座房屋。我有M个灯杆。假设M

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

2 个答案:

答案 0 :(得分: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 }`)

答案 1 :(得分:0)

我让你蒙住了芽。我将首先解释动态编程算法,如果您无法编写代码,请告诉我。

A->包含点的数组,因此A [i] -A [i-1]将是A [i]和A [i-1]之间的距离。 A [0]是第一点。当您自上而下进行记事时,您将不得不处理将灯杆放置在当前房屋或希望将其放置在较低索引处的情况。如果现在放置它,则递归少一点可用的灯杆,并计算与先前房屋的距离总和。当您不留任何灯杆或所有房屋都完蛋时,您可以处理基本情况。