标签:
解决动态规划问题的方法很多,现在先看看最容易想到的------递归法。
核心代码就那么一段:
1 int solve(int i, int j) 2 { 3 return dp[i][j] + (i == 3 ? 0 : max(solve(i + 1, j), solve(i + 1, j + 1))); 4 }
solve(i,j)就是节点(i,j)的最大值。
递推法:
思想就是从头开始一层一层推,由于每个节点上一级(最上面一个节点除外)都有两个上级节点,所以dp[i][j]就可以使它等于本身加上上一级中较大的一个数,从而不断推到底层,那么最大的肯定就在最底层了。
1 for (int i = 0; i < n; i++) 2 for (int j = 0; j < i+1; j++) 3 { 4 if (j == 0)dp[i][j] = dp[i][j]; 5 else dp[i][j] += max(dp[i - 1][j], dp[i - 1][j - 1]); 6 }
之后想到这种方法并非递推中最好的,因为还要在底层中用循环找最大值,其实最好的方法是从底层往上递推,最后结果就是dp[0][0]。
记忆化搜索:
基本是结合了前两者的特点:用递归的总体思想,但其中掺加了递推法的保存计算过的值。也就是第一次使用递归时将它得出的节点的值保存下来,以后再使用到这个节点时就可以直接使用这个值了,而不用再去递归。但里面有一点小技巧:你怎么知道它之前有没有递归算出过答案呢?就是设两个数组,第一个数组dp用来存放已经计算过的节点,第二个数组是真正完整的数组。一开始dp数组用什么东西标识(比如对于一棵树中全是整数的话就用-1来初始化dp)。
int solve(int i, int j) { if (dp[i][j] > 0)return dp[i][j]; return dp[i][j] = a[i][j] + (i == 3 ? 0 : max(solve(i + 1, j), solve(i + 1, j + 1))); }
标签:
原文地址:http://www.cnblogs.com/nkuhjp/p/5421472.html