Fork me on GitHub

【Offer】[47] 【礼物的最大价值】

题目描述

  在一个m*n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向左(以自己为视角)或者向下移动一格,直到到达棋盘的右下角。给定一个棋盘及其上面的礼物,请计算你最多能拿到多少价值的礼物?
  
  

  例如,在上面的棋盘中,如果沿着带下画线的数字的线路(1、12、5、7、7、16、5),那么我们能拿到最大价值为53的礼物。

[牛客网刷题地址]无

思路分析

  1. 动态规划。我们先用递归的思路来分析。我们先定义第一个函数f(i,j)表示到达坐标为(i,j)的格子时能拿到的礼物总和的最大值。根据题目要求,我们有两种可能的途径到达坐标为(i,j)的格子:通过格子(i-1,j)或者(i,j-1)。所以f(i,j)= max(f(i-1,j), f(i,j-1)) + gift[i,j]。gift[i,j]表示坐标为(i,j)的格子里礼物的价值。
  2. 我们可以定义缓存数组来提高效率,避免递归带来的大量重复计算的问题。

测试用例

  1. 功能测试:多行多列的矩阵;一行或者一列的矩阵;只有一个数字的矩阵。
  2. 特殊输入测试:指向矩阵数组的指针为nullptr。

Java代码

public class Offer047 {
    public static void main(String[] args) {
        test1();
        test2();
        test3();
        
    }

    public static int getMaxValue(int[][] values) {
        return Solution2(values);
    }

    /**
     * 用二位数组缓存
     * @param values
     * @return
     */
    private static int Solution1(int[][] values) {
        if(values==null || values.length<=0 || values[0].length<=0) {
            return 0;
        }
        int rows = values.length;
        int cols = values[0].length;
        int[][] maxValues = new int[rows][cols];
        for(int i=0;i<rows;i++) {
            for(int j=0;j<cols;j++) {
                int left = 0;
                int up = 0;
                if(i>0) {
                    up = maxValues[i-1][j];
                }
                if(j>0) {
                    left = maxValues[i][j-1];
                }
                maxValues[i][j] = Math.max(up,left)+values[i][j];
            }
        }
        
        return maxValues[rows-1][cols-1];
    }

    /**
     * 可以简化为一维数组
     * @param values
     * @return
     */
    private static int Solution2(int[][] values) {
        if(values==null || values.length<=0 || values[0].length<=0) {
            return 0;
        }
        int rows = values.length; //行
        int cols = values[0].length;//列
        
        int[] maxValue = new int[cols];
        for(int i=0;i<rows;i++) {
            for(int j=0;j<cols;j++) {
                int left = 0;
                int up = 0;
                if(i>0) {
                    up = maxValue[j];
                }
                if(j>0) {
                    left = maxValue[j-1];
                }
                maxValue[j] = Math.max(up,left)+values[i][j];
            }
        }
        return maxValue[cols-1];
    }

    private static void test1() {
        int[][] values = {{1,10,3,8},{12,2,9,6},{5,7,4,11},{3,7,16,5}};
        int maxValue = getMaxValue(values);
        System.out.println(maxValue);
    }

    private static void test2() {

    }
    private static void test3() {

    }
}

代码链接

剑指Offer代码-Java

posted @ 2019-08-20 11:04  这个世界~  阅读(143)  评论(0编辑  收藏  举报