题目
在一个m*n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向左或者向下移动一格,知道到达棋盘的右下角。给定一个棋盘及其上面的礼物,请计算你最多能拿多少价值的礼物?
思路
一、利用循环的动态规划
- 定义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];
- 使用循环来计算避免重复子问题。
二、优化空间复杂度,使用一维数组
每次计算拿到的礼物最大值的时候,最大值的坐标只依赖(i-1,j)and(i,j-1)两个格子,因此第i-2行及以上所有的格子礼物最大值没有必要保存下来,因此可以用一维数组代替二维数组,一维数组的长度为棋盘的列数,当我们计算坐标为(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个格子礼物的最大值。
1.
class Solution { public: int get_max_value(const vector<vector<int> > &v); }; int Solution::get_max_value(const vector<vector<int> > &v) { if(v.empty()||v.size()<=0||v[0].size()<=0) return -1; vector<vector<int>> maxValue(v.size(),vector<int>(v[0].size(),0)); for(int i=0;i<v.size();++i) { for(int j=0;j<v.at(0).size();++j) { int up=0; if(i>0) up=v.at(i-1).at(j); int left=0; if(j>0) left=v.at(i).at(j-1); maxValue.at(i).at(j)=max(up,left)+v.at(i).at(j); } } return maxValue.at(v.size()-1).at(v.at(0).size()-1); }
2.
#include <iostream> #include <vector> #include <fstream> using namespace std; class Solution { public: int get_max_value(const vector<vector<int> > &v); }; int Solution::get_max_value(const vector<vector<int> > &v) { if(v.empty()||v.size()<=0||v[0].size()<=0) return -1; //保存每一步拿到的礼物的最大值 //每次计算拿到的礼物最大值的时候,最大值的坐标只依赖(i-1,j)and(i,j-1)两个格子,因此第 //i-2行及以上所有的格子礼物最大值没有必要保存下来,因此可以用一维数组代替二维数组, //一维数组的长度为棋盘的列数,当我们计算坐标为(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个格子礼物的最大值 vector<int> value(v[0].size(),0); for(int i=0;i<v.size();++i) { for(int j=0;j<v[0].size();++j) { int left=0; int up=0; if(i>0) up=value[j]; if(j>0) left=value[j-1]; value[j]=max(up,left)+v[i][j]; } } return value[v[0].size()-1]; } int main() { ifstream in("1.txt"); vector<vector<int> > v(4,vector<int>(4,0)); for(int i=0;i<4;++i) for(int j=0;j<4;++j) in>>v[i][j]; Solution s; cout<<s.get_max_value(v)<<endl; return 0; }