题目

image.png

思路

  • 思路一:暴力递归,首先定义recur(grid, i, j)表示从(0,0)到(i,j)的礼物的最大值,因此,想要求(i,j)的最大价值,我们只需求出Math.max((i-1,j), (i, j - 1),因此递归分支为两个,我们知道(0,0)->(0,0)的礼物的最大价值就是gird[0][0],因此这个就是终止条件。
  • 思路二:备忘录
  • 思路三:动态规划,就是递归的逆过程,定义dp[i][j]表示(0,0)到(i,j)的最大礼物价值,转移方程:dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]) + grid[i][j]
  • 思路四:优化dp数组的动态规划,画图解决

    代码

    1. //1.暴力递归
    2. public int maxValue(int[][] grid) {
    3. return recur(grid, grid.length - 1, grid[0].length - 1);
    4. }
    5. public int recur(int[][] grid ,int i, int j) {
    6. if (i == 0 && j == 0) return grid[0][0];
    7. if (i < 0 || j < 0) return -1;
    8. int value1 = recur(grid, i, j - 1);
    9. int value2 = recur(grid, i - 1, j);
    10. return value1 == -1 && value2 == -1 ? -1 : Math.max(value1, value2) + grid[i][j];
    11. }
    12. //2. 备忘录
    13. int[][] dp;
    14. public int maxValue(int[][] grid) {
    15. dp = new int[grid.length][grid[0].length];
    16. return recur(grid, grid.length - 1, grid[0].length - 1);
    17. }
    18. public int recur(int[][] grid ,int i, int j) {
    19. if (i == 0 && j == 0) return grid[0][0];
    20. if (i < 0 || j < 0) return -1;
    21. if (dp[i][j] != 0) return dp[i][j];
    22. int value1 = recur(grid, i, j - 1);
    23. int value2 = recur(grid, i - 1, j);
    24. dp[i][j] = value1 == -1 && value2 == -1 ? -1 : Math.max(value1, value2) + grid[i][j];
    25. return dp[i][j];
    26. }
    27. //3.动态规划
    28. public int maxValue(int[][] grid) {
    29. //表示从(0,0)到(i,j)获得礼物的最大
    30. int[][] dp = new int[grid.length][grid[0].length];
    31. dp[0][0] = grid[0][0];
    32. for (int i = 1; i < grid.length; i++) {
    33. dp[i][0] += dp[i - 1][0] + grid[i][0];
    34. }
    35. for (int j = 1; j < grid[0].length; j++) {
    36. dp[0][j] += dp[0][j - 1] + grid[0][j];
    37. }
    38. for (int i = 1; i < grid.length; i++) {
    39. for (int j = 1; j < grid[0].length; j++) {
    40. dp[i][j] += Math.max(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
    41. }
    42. }
    43. return dp[grid.length - 1][grid[0].length - 1];
    44. }
    45. //4.优化dp数组动态规划,由于每次只用到前一行和前一个,所以可以优化为一维dp数组
    46. public int maxValue(int[][] grid) {
    47. //表示从(0,0)到(i,j)获得礼物的最大
    48. int[] dp = new int[grid[0].length];
    49. dp[0] = grid[0][0];
    50. for (int j = 1; j < grid[0].length; j++) {
    51. dp[j] += dp[j - 1] + grid[0][j];
    52. }
    53. for (int i = 1; i < grid.length; i++) {
    54. dp[0] += grid[i][0];
    55. for (int j = 1; j < grid[0].length; j++) {
    56. dp[j] = Math.max(dp[j], dp[j - 1]) + grid[i][j];
    57. }
    58. }
    59. return dp[grid[0].length - 1];
    60. }

    礼物的最大价值