动态编程表 - 打印出路径的清洁方式?

时间:2017-11-12 22:00:10

标签: javascript algorithm dynamic-programming

这是我对经典硬币收集DP问题的解决方案。一般来说,在做DP问题时,我总觉得printPath()步骤非常笨拙,比实际问题本身更混乱。

在这种情况下,从右下角开始,如果向上或向左的方向上的值是平局,只需上升即可。否则,选择包含更高或更高值的方向。如果我们到达第一排,就继续向左走。如果我们到达第一列,就继续上去。

是否有更简洁的方式printPath()

/*
given a grid
where o = coin
return the max coins you can get by only moving right or down
*/

var grid = [
  ['-','-','o','-','-','o'],
  ['-','-','-','o','-','-'],
  ['-','o','-','-','o','-'],
  ['-','-','-','o','-','-'],
  ['o','-','-','-','o','-'],
  ['-','-','o','-','-','o'],
];

function initTable(m, n, f) {
  var T = [];
  for (var r = 0; r < m; r++)
    T.push(Array(n).fill(f));
  return T;
}

function coinCollection(grid) {
  var m = grid.length, n = grid[0].length;

  var T = initTable(m+1, n+1, 0);

  for (var r = 1; r < m+1; r++) {
    for (var c = 1; c < n+1; c++) {
      var C = grid[r-1][c-1] === 'o' ? 1 : 0;
      T[r][c] = Math.max(T[r-1][c], T[r][c-1])+C;
    }
  }

  console.log({ T });

  printPath(T, m, n);

  return T[m][n];
}

function printPath(T, r, c) {
  var res = [];
  while (r !== 1 && c !== 1) {
    res.push([r, c]);
    if (T[r-1][c] === T[c][r-1] || T[r-1][c] > T[r][c-1]) {  // tie or up is more
      console.log(r, c, '↑');
      r--;
    } else {  // left is more
      console.log(r, c, '←');
      c--;
    }
  }
  if (r === 1) {  // hit first row, keep left until origin
    while (c !== 1) {  
      res.push([r, c]);
      console.log(r, c, '←');
      c--;
    }
  } else if (c === 1) {  // hit first col, keep up until origin
    while (r !== 1) {  
      res.push([r, c]);
      console.log(r, c, '↑');
      r--;
    }
  }
  console.log(r, c);
  res.push([r, c]);
  console.log({ grid, max_coins_path: res.map(([r,c]) => [r-1,c-1]).reverse() });
}

coinCollection(grid);

0 个答案:

没有答案