剑指Offer——面试题47:礼物的最大价值

面试题47:礼物的最大价值
题目:在一个m×n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向左或者向下移动一格直到到达棋盘的右下角。给定一个棋盘及其上面的礼物,请计算你最多能拿到多少价值的礼物?
例如,在下面的棋盘中,如果沿着带下划线的数字的线路(1、12、5、7、7、16、5),那么我们能拿到最大价值为53的礼物。
在这里插入图片描述
这是一个典型的能用动态规划解决的问题。我们先用递归的思路来分析。我们先定义第一个函数 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)的格子里礼物的价值。

#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
#include<cstring>
#include<cmath>
using namespace std;
int getMaxValue_solution1(const int* values, int rows, int cols){
	if(values==NULL || 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, up=0;
			if(i>0) up=maxValues[i-1][j];
			if(j>0) left=maxValues[i][j-1];
			maxValues[i][j]=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;
}
int main() {
	int value[]={1, 10, 3, 8, 12, 2, 9, 6, 5, 7, 4, 11, 3, 7, 16, 5};
	printf("%d", getMaxValue_solution1(value, 4, 4));
	return 0;
}

接下来我们考虑进一步的优化。前面我们提到,到达坐标(i, j)的格子时能够拿到的礼物的最大价值只依赖(i-1, j)和(i, j-1)的两个格子,因此第 i-2 行及更上面的所有格子礼物的最大价值实际上没有必要保存下来。我们可以用一个一维数组来替代前面代码中的二维矩阵 maxValue。该一维数组的长度为棋盘的列数 n。当我们计算到达坐标为(i, j)的格子时能够拿到的礼物的最大价值 f(i, j),数组中前 j 个数字分别是 f(i, 0),f(i, 1),……,f(i, j-1),数组从下标为 j 的数字开始到最后一个数字,分别为 f(i-1, j),f(i-1, j+1),……,f(i-1, n-1)。也就是说,该数组前面 j 个数字分别是当前第 i 行前面 j 个格子礼物的最大价值,而之后的数字分别保存前面第 i-1 行 n-j 个格子礼物的最大价值。

#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
#include<cstring>
#include<cmath>
using namespace std;
int getMaxValue_solution2(const int* values, int rows, int cols){
	if(values==NULL || 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, up=0;
			if(i>0) up=maxValues[j];
			if(j>0) left=maxValues[j-1];
			maxValues[j]=max(left, up)+values[i*cols+j];
		}
	} 
	int maxValue=maxValues[cols-1];
	delete[] maxValues;
	return maxValue;
}
int main() {
	int value[]={1, 10, 3, 8, 12, 2, 9, 6, 5, 7, 4, 11, 3, 7, 16, 5};
	printf("%d", getMaxValue_solution2(value, 4, 4));
	return 0;
}
发布了50 篇原创文章 · 获赞 51 · 访问量 2459

猜你喜欢

转载自blog.csdn.net/qq_35340189/article/details/104456649