【问题标题】:Dynamic Programming Bottoms up approach clarification [duplicate]动态规划自下而上的方法说明[重复]
【发布时间】:2021-07-06 18:27:04
【问题描述】:

所以我一直在努力掌握动态编程。我可以说我真的理解自上而下的记忆方法,但自下而上的方法让我很困惑。我能够解决自上而下切割的杆,但我必须寻求自下而上的解决方案。我只是不明白何时使用一维数组或二维数组。然后自下而上的 for 循环只是令人困惑。谁能帮我从概念上理解这两个代码的区别?

// Top Down Memoizaton: 

const solveRodCuttingTop = function(lengths, prices, n) {
  return solveRodCuttingHelper(0, lengths, prices, n); 
};

function solveRodCuttingHelper(idx, span, prices, n, memo = []) {
  // BASE CASES 
  if (idx === span.length || n <= 0 || prices.length !== span.length) {
    return 0;
  }
  let included = 0, excluded = 0; 
  memo[idx] = memo[idx] || []; 

  if (memo[idx][n] !== undefined) return memo[idx][n]; 

  if (span[idx] <= n) {
    included = prices[idx] + solveRodCuttingHelper(idx, span, prices, n - span[idx], memo);
  }

  excluded = solveRodCuttingHelper(idx + 1, span, prices, n, memo);

  memo[idx][n] = Math.max(included, excluded); 
  
  return memo[idx][n];
}



// Bottoms up 
const solveRodCuttingBottom = function(lengths, prices, n) {
  const rods = Array.from({length: n + 1});
  rods[0] = 0; 
  let maxRevenue = - Infinity;

  for (let i = 1; i < rods.length; i++) {
    for (let j = 1; j <= i; j++) {
      maxRevenue = Math.max(maxRevenue, prices[j - 1] + rods[i - j])
    }
    rods[i] = maxRevenue
  }
  return rods[prices.length];
};

const lengths = [1, 2, 3, 4, 5];
const prices = [2, 6, 7, 10, 13];

【问题讨论】:

  • 到底有什么令人困惑的地方?对于 TD,您说:“我无法解决这个问题,因为它太大了。我需要先解决小问题,然后再建立大解决方案”。对于 BU,您说:“我从解决较小的问题开始,然后建立大的解决方案”。无论哪种方式,您最终都会先解决小问题并构建大问题,这只是您从哪里开始的问题。到目前为止,备忘录哈希和DP表是存储子问题解决方案的两种方式。

标签: javascript recursion


【解决方案1】:

这是一个有趣的问题。也许我把它过分简化了,但如果你首先计算每个pricelength,你可以通过以最高价格尽可能多地销售来确定解决方案。如果剩余的杆太短而无法以最佳价格出售,请转到下一个最佳价格并继续。

为了使用这种技术解决问题,我们首先实现一个createMarket 函数,该函数以lenghtsprices 作为输入,并计算每长度价格rate。最后市场是sorted by rate in descending order -

const createMarket = (lengths, prices) =>
  lengths.map((l, i) => ({
    length: l,                      // length
    price: prices[i],               // price
    rate: prices[i] / l             // price per length
  }))
  .sort((a, b) => b.rate - a.rate)  // sort by price desc

const lengths = [1, 2, 3, 4, 5]
const prices = [2, 6, 7, 10, 13]

console.log(createMarket(lengths, prices))
[
  { length: 2, price: 6, rate: 3 },
  { length: 5, price: 13, rate: 2.6 },
  { length: 4, price: 10, rate: 2.5 },
  { length: 3, price: 7, rate: 2.3333333333333335 },
  { length: 1, price: 2, rate: 2 }
]

接下来我们编写递归的solve 来接受市场,[m, ...more]rod 来进行买卖。解决方案sln,默认为[] -

const solve = ([m, ...more], rod, sln = []) =>
  m == null
    ? sln
: m.length > rod
    ? solve(more, rod, sln)
: solve([m, ...more], rod - m.length, [m, ...sln])

const result =
  solve(createMarket(lengths, prices), 11)

console.log(result)
[
  { length: 1, price: 2, rate: 2 },
  { length: 2, price: 6, rate: 3 },
  { length: 2, price: 6, rate: 3 },
  { length: 2, price: 6, rate: 3 },
  { length: 2, price: 6, rate: 3 },
  { length: 2, price: 6, rate: 3 }
]

在上面,solve 返回总和为最高价格的杆长度。如果你想要总价,我们可以reduce结果和price相加-

const bestPrice =
  solve(createMarket(lengths, prices), 11)
    .reduce((sum, r) => sum + r.price, 0)

console.log(bestPrice)
32

【讨论】:

    猜你喜欢
    • 2013-10-05
    • 2019-08-28
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 2019-07-26
    • 2014-05-20
    • 2014-07-28
    • 2021-11-10
    相关资源
    最近更新 更多