边界问题
问题1:状态表示
问题2:状态如何计算
问题3:边界
问题1:状态表示 f(i,j),表示从左上角走到(i,j)这个格子时,我拿到礼物的价值是多少
问题2:状态如何计算 f(i,j)=max{f[i-1,j],f[i,j-1]}+gift[i,j]
其中:gift[i,j]为目标格子的礼物价值;
max{f[i-1,j],f[i,j-1]}为到达目标前的累计礼物最大值
问题3:边界 f[i,0]=f[0,j]=0
答案:f(n,m)
class Solution { public: int getMaxValue(vector<vector<int>>& grid) { int m = grid.size(), n = grid[0].size(); vector<vector<int>> f(m + 1, vector<int>(n + 1));//下标从1开始算,从1开始算,不用处理边界问题。从1开始算,i-1其实是0 // 从1开始可以不用处理边界问题 for(int i = 1; i <= m; i ++){ for(int j = 1; j <= n; j ++){ //因为我们的i,j是从1开始算的,所以进行了i-1,j-1。所以i和j都要往前偏1个 f[i][j] = max(f[i - 1][j] + grid[i - 1][j - 1], f[i][j - 1] + grid[i - 1][j - 1]);
//cout <<"f[i - 1][j]="<<f[i - 1][j]<<" "<< "f[i][j - 1])=" <<f[i][j - 1]<<endl;
//cout <<"grid[i - 1][j - 1]="<<grid[i - 1][j - 1]<<endl;
//cout <<"f[i][j]="<<f[i][j]<<endl; } } return f[m][n]; } };
代码中不理解,
1.为什么数组f的长度要定义成(m+1)*(n+1)
以测试函数为例,结合代码一步步看一下这是为什么?
输入如上,则m=n=3,
f(m + 1, vector<int>(n + 1))为4*4;
为什么是4不是3呢?
看下图
i=0~3, j=0~3除了(i=0,j=0)没有被用到,其他的都用了。所以数组f的长度要定义成(m+1)*(n+1)没毛病。
第二个问题,为什么f[i][j] = max(f[i - 1][j] + grid[i - 1][j - 1], f[i][j - 1] + grid[i - 1][j - 1]);用 的是 grid[i - 1][j - 1]而不是我们分析的grid[i][j]。
同样是结合输入数组
for循环中i,j初始值为1,而g的下标是从0开始的,所以用 的是 grid[i - 1][j - 1]而不是我们分析的grid[i][j]