面试题47:礼物的最大值

题目:

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

分析:

这是一个动态规划问题,我们使用递归的思路分析。定义一个函数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)格子里礼物的价值。

因为递归有大量重复计算,所以我们使用递归分析思路,使用递推求解。

我们需要一个辅助二维数组,将中间的计算结果缓存进来。

这个问题还可以进一步优化,到达坐标(i,j)时候最大价值依赖于(i-1,j)和(i,j-1),因此第i-2行及上面的所有格子的最大价值实际上没必要保存下来,于是可以使用一个一维数组代替之前的二维数组。当我们计算(i,j)格子能拿到的最大价值的时候,一维数组中,前j个数字是f(i,0),f(i,1),……f(i,j-1),数组从下标j的数字到最后,分别为f(i01,j),f(i-1,j+1)……f(i-1,n-1)。也就是前j个保存当前行前j个位置的最大价值,后面的数字保存的是上一行n-j个位置的最大价值。

解法:

package com.wsy;

public class Main {
    public static int[][] gift;

    public static void main(String[] args) {
        gift = new int[][]{{1, 10, 3, 8}, {12, 2, 9, 6}, {5, 7, 4, 11}, {3, 7, 16, 5}};
        getMaxValue();
    }

    public static void getMaxValue() {
        if (gift == null) {
            return;
        }
        int rows = gift.length;
        int cols = gift[0].length;
        int[][] maxValue = 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 = maxValue[i - 1][j];
                }
                if (j > 0) {
                    left = maxValue[i][j - 1];
                }
                maxValue[i][j] = Math.max(up, left) + gift[i][j];
            }
        }
        System.out.println("maxValue=" + maxValue[rows - 1][cols - 1]);
    }
}
package com.wsy;

public class Main {
    public static int[][] gift;

    public static void main(String[] args) {
        gift = new int[][]{{1, 10, 3, 8}, {12, 2, 9, 6}, {5, 7, 4, 11}, {3, 7, 16, 5}};
        getMaxValue();
    }

    public static void getMaxValue() {
        if (gift == null) {
            return;
        }
        int rows = gift.length;
        int cols = gift[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) + gift[i][j];
            }
        }
        System.out.println("maxValue=" + maxValue[cols - 1]);
    }
}
发布了181 篇原创文章 · 获赞 1 · 访问量 7457

猜你喜欢

转载自blog.csdn.net/qq_36059561/article/details/104348693