49.剑指Offer-礼物的最大价值

题目描述

小东所在公司要发年终奖,而小东恰好获得了最高福利,他要在公司年会上参与一个抽奖游戏,游戏在一个6*6的棋盘上进行,上面放着36个价值不等的礼物,每个小的棋盘上面放置着一个礼物,他需要从左上角开始游戏,每次只能向下或者向右移动一步,到达右下角停止,一路上的格子里的礼物小东都能拿到,请设计一个算法使小东拿到价值最高的礼物。

给定一个6*6的矩阵board,其中每个元素为对应格子的礼物价值,左上角为[0,0],请返回能获得的最大价值,保证每个礼物价值大于100小于1000。

 

在一个 m*n 的棋盘的每一个格都放有一个礼物,每个礼物都有一定价值(大于 0)。从左上角开始拿礼物,每次向右或向下移动一格,直到右下角结束。给定一个棋盘,求拿到礼物的最大价值。例如,对于如下棋盘

1    10   3    8
12   2    9    6
5    7    4    11
3    7    16   5

礼物的最大价值为 1+12+5+7+7+16+5=53。

解题思路

应该用动态规划求解,而不是深度优先搜索,深度优先搜索过于复杂,不是最优解。

public int getMost(int[][] values) {
    if (values == null || values.length == 0 || values[0].length == 0)
        return 0;
    int n = values[0].length;
    int[] dp = new int[n];
    for (int[] value : values) {
        dp[0] += value[0];
        for (int i = 1; i < n; i++)
            dp[i] = Math.max(dp[i], dp[i - 1]) + value[i];
    }
    return dp[n - 1];
}

使用递归找出所有的情况:

public class BigestGift {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[][] arr={{1,10,3,8},{12,2,9,6},{5,7,4,11},{3,7,16,5}};
		int max=getMost(arr);
		System.out.println(max);
	}
	public static int getMost(int[][] board) {
		int max=nextStep(board,0,0);
		return max;
	}
	public static int nextStep(int[][] board,int x,int y){
		if(x==board.length-1&&y==board[0].length-1){
			return board[x][y];
		}
		if(x>=board.length||y>=board[0].length){
			return Integer.MIN_VALUE;
		}else{
			return Math.max(nextStep(board,x,y+1)+board[x][y], nextStep(board,x+1,y)+board[x][y]);
		}
	}
}

49.剑指Offer-礼物的最大价值_第1张图片

从图上可以看到递归的时候会计算很多重复的地方。使用递归的时候,只要想好要传入下一次递归的参数,边界情况怎么处理,要返回的是什么值,递归思路基本上就出来了。递归算是一种暴利破解的方式,将所有情况都试一遍找出最好的。还是推荐使用第一种动态规划的方式,想好dp的每一步与前一步的关系,通过保存前一步的最优值,减少重复计算。

你可能感兴趣的:(剑指Offer)