算法---礼物的最大值

在一个 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)的顺序可以拿到总价值最大的礼物。礼物的最大价值为1+12+5+7+7+16+5=53。

思路一:递归,定义一个函数f(i,j)用来表示到达坐标为(i,j)的格子时能拿到的礼物总和的最大值,根据题意只能从右走和下走,所以对当前点(i,j)来说,最大值只需比较左边和上面的。另外考虑当处在上边界和左边界的情况时只有一个方向可以走。

	public static int getMaxValue(int[][]a){
	
		int max = 0;
		int i = a.length;
		int j = a[0].length;
		max = sum(a,i,j);
		return max;
	}

private static int sum(int[][] a,int row,int col) {
	
	//当来到左上角时,终止条件
	if(row==1&&col==1)
		return a[0][0];
	//当来到上边界,只能往左走
	if(row==1)
		return sum(a, row, col-1)+a[row-1][col-1];
	//当来到左边界,只能往上走
	else if(col==1)
		return sum(a, row-1, col) + a[row-1][col-1];
	//否则判断是哪边大
	else
		return Math.max(sum(a, row, col-1), sum(a, row-1, col))+a[row-1][col-1];
		
	
	
}

思路二:采用动态规划,因为递归会存在大量的重复计算,效率很低,我们可以采用一个二维数组来保存当前点的最大值,这样就可以计算得右下角那点的最大值。

public static int getMaxValue(int[][] a) {
		if(a==null||a.length==0||a[0].length==0)
			return 0;
		int row = a.length;
		int col = a[0].length;
		//定义二维数组来保存中间结果
		int[][] maxValues = new int[row][col];
		for(int i = 0;i < row;i++)
			for(int j =0;j < col;j++)
			{
				//原点
				if(i==0 && j==0)
				{
					maxValues[i][j] = a[i][j];
				}
				//上边界
				else if(i==0 && j!=0)
				{
					maxValues[i][j] = a[i][j] + maxValues[i][j-1];
				} 
				//左边界
				else if(i!=0&&j==0)
				{
					maxValues[i][j] = a[i][j] + maxValues[i-1][j];
				}
				else {
					maxValues[i][j] = a[i][j] + Math.max(maxValues[i][j-1], maxValues[i-1][j]);
				}

			}
		return maxValues[row-1][col-1];
	}

思路三:因为节点一直是往右下走的,所以i-2行的数据并不需要保存。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值