【DP】礼物的最大价值

版权声明:本文为博主原创学习笔记,如需转载请注明来源。 https://blog.csdn.net/SHU15121856/article/details/82694596

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

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

之前Python课也做过这题,因为f(i,j)只依赖左边的一个礼物和上边的一个礼物,可以仅用一个数组将路径堵死向下刮,而不需要保存整个矩阵。
这里写图片描述

#include<bits/stdc++.h>
using namespace std;

//给出礼物矩阵的一维数组形式,行数,列数,求从矩阵中能获取的礼物的最大值
int getMaxValue_solution(const int* values, int rows, int cols) {
	if(values == nullptr || rows <= 0 || cols <= 0)//输入合法性检查
		return 0;

	//拦路数组:0~j-1=>f(i,0)~f(i,j-1);j~cols=>f(i-1,j)~f(i-1,cols-1)
	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)//i>0时上边礼物存在
				up = maxValues[j];//f(i-1,j)存在mV[j]位置

			if(j > 0)//j>0时左边礼物存在
				left = maxValues[j - 1];//f(i,j-1)存在mV[j-1]位置

			//当前位置的礼物最大价值=左边和上边中大价值的一个+当前位置价值
			maxValues[j] = max(left, up) + values[i * cols + j];
		}
	}

	//最后跑完了整个矩阵,右下角位置的最大价值是该数组最右元素
	int maxValue = maxValues[cols - 1];

	delete[] maxValues;

	return maxValue;
}

int main() {
	int values[][4] = {
		{ 1, 10, 3, 8 },
		{ 12, 2, 9, 6 },
		{ 5, 7, 4, 11 },
		{ 3, 7, 16, 5 }
	};
	
	cout<<getMaxValue_solution((int *)(values),4,4)<<endl;

	return 0;
}

感觉这种省空间的做法很精妙,从上面图中可以看出,这个数组的前半部分(蓝色部分)在行内从左到右循环时逐渐建立起来,而后半部分(紫色部分)则是上一行的循环中计算出而保留在数组内的,在前半部分扩张时逐步地覆盖掉了上次计算的后半部分。

另外,数组中指示当前考察的元素(绿色部分)每次使用到了其左边和其上边的两个元素,这两个元素正式这个数组中“前半部分”和“后半部分”交界之处。

猜你喜欢

转载自blog.csdn.net/SHU15121856/article/details/82694596