面试题47. 礼物的最大价值

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

示例

输入: [ [1,3,1], [1,5,1], [4,2,1] ]
输出: 12
解释: 路径 1→3→5→2→1可以拿到最多价值的礼物

提示:0 < grid.length <= 200;0 < grid[0].length <= 200

思路: 动态规划

这是一个典型利用动态规划的题目。那我们现在来看一下思考这个问题,如何用动态规划解决。

求解最优问题,那么就一定要先想到动态规划,还是先从三个方面入手:如何用数组来存储最大价值,转移方程,空间是否优化:

  1. 数组存储:从左上角开始走,到右下角得到最大价值,那么dp数组每次保存从左上角到dp[i] [j]的礼物最大价值,最后我们返回数组右下角的值即可,每次dp[i] [j]保存最大值,那么可以观察数组的关系,得到转移方程。

  2. 转移方程 :从左上角出发,每次只能向右或者向下走,就表示从左上角到dp[i] [j]的取值由它自身,左边的值或上边的值决定,即dp[i] [j],dp[i-1] [j],dp[i] [j-1];因为我们每次保存最大值,所以dp[i] [j]=dp[i] [j]+max(dp[i-1] [j],dp[i] [j-1])可以确定dp[i] [j]的值。但我们不要忘了边界,第一列和第一行的dp[i] [j]确定,第一行不能由上面的值确定,第一列不能由左边的值确定。还有dp[0] [0] 的值为自身,所以单独赋值。

    那我们总结上述情况,写出状态转移方程:

    • 当 i=0,j=0时,为起始元素,dp[0] [0]=grid[0] [0];
    • 当 i=0,j ≠0时,为第一行,只可以从左边到达,故由左边的值dp[i] [j-1]决定,dp[i] [j]=dp[i] [j]+dp[i] [j-1];
    • 当 i≠0,j=0,为第一列,只可以从上面到达,故由上面的值dp[i-1] [j]决定,dp[i] [j]=dp[i] [j]+p[i-1] [j];
    • 当 i ≠0,j ≠0,那么即可以从上面到达也可以从左边,所以dp[i] [j]=dp[i] [j]+max(dp[i-1] [j],dp[i] [j-1])
  3. 空间优化:我们可以在原数组的基础上来改变数值,得到最大值。我偷个懒没有优化数组,但可以优化。

那我们通过示例看一下:
面试题47. 礼物的最大价值_第1张图片
那我们就可以写出代码:

int maxValue(vector<vector<int>>& grid) 
{
	if(grid.empty())
		return 0;

	int m=grid.size();
	int n=grid[0].size();
	vector<vector<int>> dp(m,vector<int>(n,0));//dp数组初始化为0
	for(int i=0;i<m;i++)
	{
		for(int j=0;j<n;j++)
		{
			if(j==0&&i==0)
			{
				dp[i][j]=grid[0][0];//初始化
				continue;
			}
			if(i<=0)//处理第一行
			{
				dp[i][j]=dp[i][j-1]+grid[i][j];
				continue;//必须要写
			}
			if(j<=0)//处理第一列
			{
				dp[i][j]=dp[i-1][j]+grid[i][j];
				continue;
			}
			else
				dp[i][j]=max(dp[i-1][j]+grid[i][j],dp[i][j-1]+grid[i][j]);
		}
	}
	return dp[m-1][n-1];
}
int main()
{
	vector<vector<int>> grid;
	vector<int> temp;
	temp.push_back(1);
	temp.push_back(3);
	temp.push_back(1);
	grid.push_back(temp);
	temp.clear();
	temp.push_back(1);
	temp.push_back(5);
	temp.push_back(1);
	grid.push_back(temp);
	temp.clear();
	temp.push_back(4);
	temp.push_back(2);
	temp.push_back(5);
	grid.push_back(temp);
	
	cout<<maxValue(grid); 
}

加油哦!。

你可能感兴趣的:(剑指offer习题练习)