两种方法一个从上往下,一个从下往上。
算法一
dfs + 备忘录
按dfs思想,枚举所有可能的礼物组合,当前在i,j格子,有两种选择down right 。dfs定义为可以求这两个方向的最大的礼物值,然后取max(dfs(down),dfs(up)) + grid[i][j] = dfs((i,j))的值。
期间判断是否已经枚举过这个组合,若枚举过,则用备忘录加速运算,不然会mle。
时间复杂度:O(){求分析}
class Solution {
public:
int getMaxValue(vector<vector<int>>& grid) {
vector<vector<int>> dp(grid.size(),vector<int>(grid[0].size(),-1));
return dfs(grid,0,0,dp);
}
int dfs(vector<vector<int>>& grid,int x,int y,vector<vector<int>> &dp)//返回一个点最大的路径
{
if(x == grid.size()-1 && y == grid[x].size() - 1) return grid[x][y] ;//最右下角
if(dp[x][y] != -1) return dp[x][y];//加速
else{//没有,则算一下
if(y < grid[x].size() -1 && dp[x][y+1] == -1) dp[x][y+1] = dfs(grid,x,y+1,dp);//加速
if(x < grid.size() - 1 && dp[x+1][y] == -1) dp[x+1][y] = dfs(grid,x+1,y,dp);//加速
if(x < grid.size() - 1 && y < grid[x].size() -1 )//判断边界的情况,有三种
dp[x][y] = max(dp[x+1][y],dp[x][y+1]) ;
else if(x < grid.size() - 1 && y == grid[x].size() -1)
dp[x][y] = dp[x+1][y];
else if(y < grid[x].size() -1 && x == grid.size() - 1)
dp[x][y] = dp[x][y+1];
dp[x][y] += grid[x][y];
return dp[x][y];
}
}
};
算法二
动态规划
时间复杂度O(n^2)
dp[i][j]为当前所在格子。要求礼物最大,题目的down left 可以变换为最大的left up最大。
因此dp[i][j] = max(dp[i-1[j],dp[i][j-1]) + grid[i][j]
class Solution {
public:
int getMaxValue(vector<vector<int>>& grid) {
vector<vector<int>> dp(grid.size(),vector<int>(grid[0].size(),0));
dp[0][0] = grid[0][0];
//base case 1://no left
for(int i = 1; i < grid.size(); i ++)
{
dp[i][0] = dp[i-1][0] + grid[i][0];
}
//base case 2://no up
for(int i = 1; i < grid[0].size(); i++)
{
dp[0][i] = dp[0][i-1] + grid[0][i];
}
for(int i = 1; i < grid.size(); i ++)
{
for(int j = 1; j < grid[i].size(); j++)
{
dp[i][j] = max(dp[i-1][j],dp[i][j-1])+grid[i][j];
}
}
return dp[grid.size()-1][grid[0].size()-1];
}
};
https://www.acwing.com/problem/content/description/56/
60题