47 礼物的最大值

题目

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

比如说现在有一个如下的棋盘:

在这个棋盘中,按照(1,12,5,7,7,16,5)的顺序可以拿到总价值最大的礼物。

C++ 题解

  • 使用动态规划求解。
  • 定义一个函数\(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)]+g(i,j); \]

其中\(g(i,j)\)表示格子\((i,j)\)的礼物的价值。

  • 设置一个和棋盘相同大小\(m×n\)的矩阵\(dp\),用来储存达到每个格子能拿到的礼物的最大值。

方法一

借助一个二维的数组:

int getMaxValue(const int* values, int rows, int cols)
{
	if (values == nullptr || rows <= 0 || cols <= 0)
		return 0;

	int** maxValues = new int*[rows];
	for (int i = 0; i < rows; ++i)
		maxValues[i] = 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 = maxValues[i - 1][j];

			if (j > 0)
				left = maxValues[i][j - 1];

			maxValues[i][j] = std::max(left, up) + values[i * cols + j];
		}
	}

	int maxValue = maxValues[rows - 1][cols - 1];

	for (int i = 0; i < rows; ++i)
		delete[] maxValues[i];
	delete[] maxValues;

	return maxValue;
}

方法二

注意到计算每一格能拿到的礼物的最大值时,总是只使用了前一格和上面一格的值,所以理论上我们只需要维护一行数据即可,该行数据的长度为棋盘的列数n。
借助一个一维的数组:

int getMaxValue(const int* values, int rows, int cols)
{
	if (values == nullptr || rows <= 0 || cols <= 0)
		return 0;

	int* maxValues = 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 = maxValues[j];

			if (j > 0)
				left = maxValues[j - 1];

			maxValues[j] = std::max(left, up) + values[i * cols + j];
		}
	}

	int maxValue = maxValues[cols - 1];

	delete[] maxValues;

	return maxValue;
}

python 题解

方法一

借助一个二维的数组:

# -*- coding:utf-8 -*-
class Solution:
    #假设输入array为一维数组,行数为rows,列数为cols,要求输出为最大的那个数值
    def getMaxValue1(self,array,rows,cols):
        # write code here
        if array==[] or rows<=0 or cols<=0:
            return 0
        maxValues=[[0 for i in range(cols)] for j in range(rows)]
        for i in range(rows):
            for j in range(cols):
                left=0
                up=0
                if i>0: 
                    #如果行号大于0,说明它上面有数字
                    up=maxValues[i-1][j]
                if j>0:
                    #如果列号大于0,说明它左边有数字
                    left=maxValues[i][j-1]
                maxValues[i][j]=max(up,left)+array[i*cols+j]

        return maxValues[rows-1][cols-1]

方法二

借助一个一维的数组:

# -*- coding:utf-8 -*-
class Solution:
    #假设输入array为一维数组,行数为rows,列数为cols,要求输出为最大的那个数值
    def getMaxValue2(self, array, rows, cols):
        # write code here
        if array == [] or rows <= 0 or cols <= 0:
            return 0
        maxValues=[0 for i in range(cols)]

        for i in range(rows):
            for j in range(cols):
                up=0
                left=0
                if i>0:
                    #如果行号大于0,说明它上面有数字。up仍为当前列的maxValue
                    up=maxValues[j]
                if j>0:
                    #如果列号大于0,说明它左边有数字。
                    left=maxValues[j-1]
                maxValues[j]=max(up,left)+array[i*cols+j]
        return maxValues[cols-1]
posted @ 2019-03-16 18:45  youngliu91  阅读(426)  评论(0)    收藏  举报