LeetCode 741. 摘樱桃

290 阅读1分钟

网页捕获_10-7-2022_125146_leetcode.cn.jpeg 从左上角走到右下角再走回来等同于左上角到右下角走两次并且路径可以重复 f[i,j]表示所有从(1,1)走到(i,j)路径的最大值 f[i,j]=max(f[i-1,j]+w[i,j],f[i,j-1]+w[i,j])

走两次: f[i1,j1,i2,j2]表示所有从(1,1),(1,1)走到(i1,j1),(i2,j2)的路径最大值 因为每走一步横纵坐标的和总是相同所以可以将状态压缩为f[k,i1,i2],k为横纵坐标之和,因此i1+j1=k,i2+j2=k 因为路径可以重复并且走过后该点值变为0所以当i1==i2时不再累加grid

  • 注意: grid中迷宫范围是(0,0)到(n-1,n-1) f状态的迷宫范围是(1,1)到(n,n)
const int N=55;
class Solution {
    int f[2*N][N][N];
public:
    int cherryPickup(vector<vector<int>>& grid) {
        int n = grid.size();
        memset(f, -0x3f, sizeof f);
        if (grid[0][0] != -1) f[2][1][1] = grid[0][0];//当起点不为-1初始化f数组
        for(int k=3;k<=2*n;k++){//k=3从走了第一步开始
            for(int i1=1;i1<=n;i1++){
                for(int i2=1;i2<=n;i2++){
                    int j1=k-i1,j2=k-i2;
                    if(j1>=1 &&j1<=n&&j2>=1&&j2<=n) {
                    if(grid[i1-1][j1-1]==-1 || grid[i2-1][j2-1]==-1) continue;         
                    int t=grid[i1-1][j1-1];
                    if(i1!=i2) t+=grid[i2-1][j2-1];
                    int &x=f[k][i1][i2];
                    x=max(x,f[k-1][i1-1][i2]+t);
                    x=max(x,f[k-1][i1-1][i2-1]+t);
                    x=max(x,f[k-1][i1][i2-1]+t);
                    x=max(x,f[k-1][i1][i2]+t);
                    } 
                }
            }
        }
        return max(0,f[2*n][n][n]);
    }
};