@iar
2015-10-29T00:19:35.000000Z
字数 6160
阅读 141
POJ DP
题目链接
+ 经典的DP问题. 类似的有max triangle sum. 这类题目是找最值, 并且到达每个点有多种路径. 所以是DP. 还有个关键就是DP的3个条件. 以及4要素.
steps[i][j] = Max{steps[i-1][j], steps[i+1][j], steps[i][j-1], steps[i][j+1]} + 1. 或者说:
node[][]如下:1 5 69 4 72 3 8计算完res00后, path是:5 4 31 0 20 0 1------reset path[][], 计算res20, path是: 因为到达[2,0]的最优解是7.0 4 31 5 27 6 1接着计算完res10后, path是: 因为没有到达[1,0]的点, 所以返回rs+1= 1.0 4 31 5 27 6 1而不是0 0 01 0 00 0 0还有很重要的点就是: 从上面可以看出来每个子问题计算完之后就是最后的值, 例如[0,0]的最优解是5, 并不会因为我call helper(node, path, 1,0)而改变. 因为很简单: 到达每个点的最优解只有1个!
private int helper(int[][] node, int[][] path, int r, int c) {// 居然没有base case? 因为这个是求最值的DP, 类似于smilence的笔记里面所说的聚合问题(我觉得应该叫发散, 因为是从要求的点[i,j], 发散求出所有子问题的解, 然后再聚合回到这个点). 所以是topdown, 但不是backtracking.int rs = 0;for (int i = 0; i < 4; ++i) {int next_r = r + dx[i];int next_c = c + dy[i];if (isValid(node, r, c, next_r, next_c)) {if (path[next_r][next_c] > 0) {rs = Math.max(path[r][c], path[next_r][next_c]+1);}else {rs = Math.max(path[r][c], helper(node, path, next_r, next_c) + 1);}}}return path[r][c] = rs+1;}
我一开始想就是: 按照Knight tour/pattern matching那样写. 即
但是我没想到base case怎么写.
helper()的signiture怎么写?
peak helper(node, r, c, Row, Col)就返回到达[r,c]的最远距离.
private int helperDouban(int[][] node, int[][] path, int r, int c) {if (path[r][c] > 0) {return path[r][c];}for (int i = 0; i < 4; ++i) {int next_r = r + dx[i];int next_c = c + dy[i];if (isValid(node, r, c, next_r, next_c, node.length, node[0].length)) {path[r][c] = Math.max(path[r][c], helperDouban(node, path, next_r, next_c) + 1);}}return path[r][c];}
path[r][c] = Math.max(path[r][c], helperDouban(node, path, next_r, next_c).
1 2 3 412 13 14 511 16 15 610 9 8 7
往往DP问题是求解最优解. 即1个值而已. 然后follow up常考返回得到最优解的最优方案, 例如路径之类的.
+ 有2个方法: 一个就是ALgorithm Stanford的课一样, 通过DP table, 一个个找回去到起点. 还有一个方法就是在DP的过程中update 最优方案.
lujing[r][c].addAll(lujing[next_r][next_c]);. 还有个问题就是, 既然要走4个方向, 并用最长那个, 那么我加了之后, 怎么再换个方向发现更好的时候remove掉呢? 需要一个temp var记录之前加上的长度. 那么这个temp var就要相对于4次换方向来说是global的. 所以就像九章主页君的一个recursion那个题目?, 那样, 使用一个for loop之外的var. 用来记录4次的长度. 只要有更好的, 就remove掉. 再加上这次的list.
private int helperP(int[][] node, int[][] path, List<Integer>[][] list, int r, int c) {int rs = 0;int lastSize = 0;for (int i = 0; i < 4; ++i) {int rr = r + dx[i];int cc = c + dy[i];if (isValid(node, r, c, rr, cc, node.length, node[0].length)) {if (path[rr][cc] != 0) {if (rs < path[rr][cc]) {for (int id = 0; id < lastSize; ++id) {list[r][c].remove(list[r][c].size() - 1);}list[r][c].addAll(list[rr][cc]); //add(node[rr][cc]); //lastSize = list[rr][cc].size();rs = path[rr][cc];}}else {int tmp = helperP(node, path, list, rr, cc);if (tmp > rs) {rs = tmp;for (int id = 0; id < lastSize; ++id) {list[r][c].remove(list[r][c].size() - 1);}list[r][c].addAll(list[rr][cc]); // add(node[rr][cc]);lastSize = list[rr][cc].size();}}}}