列表

详情


1463. 摘樱桃 II

给你一个 rows x cols 的矩阵 grid 来表示一块樱桃地。 grid 中每个格子的数字表示你能获得的樱桃数目。

你有两个机器人帮你收集樱桃,机器人 1 从左上角格子 (0,0) 出发,机器人 2 从右上角格子 (0, cols-1) 出发。

请你按照如下规则,返回两个机器人能收集的最多樱桃数目:

 

示例 1:

输入:grid = [[3,1,1],[2,5,1],[1,5,5],[2,1,1]]
输出:24
解释:机器人 1 和机器人 2 的路径在上图中分别用绿色和蓝色表示。
机器人 1 摘的樱桃数目为 (3 + 2 + 5 + 2) = 12 。
机器人 2 摘的樱桃数目为 (1 + 5 + 5 + 1) = 12 。
樱桃总数为: 12 + 12 = 24 。

示例 2:

输入:grid = [[1,0,0,0,0,0,1],[2,0,0,0,0,3,0],[2,0,9,0,0,0,0],[0,3,0,5,4,0,0],[1,0,2,3,0,0,6]]
输出:28
解释:机器人 1 和机器人 2 的路径在上图中分别用绿色和蓝色表示。
机器人 1 摘的樱桃数目为 (1 + 9 + 5 + 2) = 17 。
机器人 2 摘的樱桃数目为 (1 + 3 + 4 + 3) = 11 。
樱桃总数为: 17 + 11 = 28 。

示例 3:

输入:grid = [[1,0,0,3],[0,0,0,3],[0,0,3,3],[9,0,3,3]]
输出:22

示例 4:

输入:grid = [[1,1],[1,1]]
输出:4

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: int cherryPickup(vector<vector<int>>& grid) { } };

rust 解法, 执行用时: 17 ms, 内存消耗: 2.2 MB, 提交时间: 2024-05-07 07:36:05

impl Solution {
    pub fn cherry_pickup(grid: Vec<Vec<i32>>) -> i32 {
        let m = grid.len();
        let n = grid[0].len();
        let mut f = vec![vec![-1; n]; n];
        let mut g = vec![vec![-1; n]; n];

        f[0][n - 1] = grid[0][0] + grid[0][n - 1];
        for i in 1..m {
            for j1 in 0..n {
                for j2 in 0..n {
                    let mut best = -1;
                    for dj1 in -1..=1 {
                        for dj2 in -1..=1 {
                            let dj1 = j1 as i32 + dj1;
                            let dj2 = j2 as i32 + dj2;
                            if dj1 >= 0 && dj1 < n as i32 && dj2 >= 0 && dj2 < n as i32 && f[dj1 as usize][dj2 as usize] != -1 {
                                best = best.max(f[dj1 as usize][dj2 as usize] + if j1 == j2 { grid[i][j1] } else { grid[i][j1] + grid[i][j2] });
                            }
                        }
                    }
                    g[j1][j2] = best;
                }
            }
            std::mem::swap(&mut f, &mut g);
        }

        let mut ans = 0;
        for j1 in 0..n {
            ans = ans.max(*f[j1].iter().max().unwrap_or(&0));
        }
        ans
    }
}

javascript 解法, 执行用时: 106 ms, 内存消耗: 52.4 MB, 提交时间: 2024-05-07 07:35:46

/**
 * @param {number[][]} grid
 * @return {number}
 */
var cherryPickup = function(grid) {
    const m = grid.length;
    const n = grid[0].length;

    let f = Array.from({ length: n }, () => Array(n).fill(-1));
    let g = Array.from({ length: n }, () => Array(n).fill(-1));

    f[0][n - 1] = grid[0][0] + grid[0][n - 1];
    for (let i = 1; i < m; ++i) {
        for (let j1 = 0; j1 < n; ++j1) {
            for (let j2 = 0; j2 < n; ++j2) {
                let best = -1;
                for (let dj1 = j1 - 1; dj1 <= j1 + 1; ++dj1) {
                    for (let dj2 = j2 - 1; dj2 <= j2 + 1; ++dj2) {
                        if (dj1 >= 0 && dj1 < n && dj2 >= 0 && dj2 < n && f[dj1][dj2] != -1) {
                            best = Math.max(best, f[dj1][dj2] + (j1 == j2 ? grid[i][j1] : grid[i][j1] + grid[i][j2]));
                        }
                    }
                }
                g[j1][j2] = best;
            }
        }
        [f, g] = [g, f];
    }
    let ans = 0;
    for (let j1 = 0; j1 < n; ++j1) {
        ans = Math.max(ans, Math.max(...f[j1]));
    }
    return ans;
};

golang 解法, 执行用时: 16 ms, 内存消耗: 6.4 MB, 提交时间: 2023-09-21 23:23:50

func cherryPickup(grid [][]int) int {
    // f[i][j][k]   表示第i行摘取j,k桃子的最大值    // 令j<k
    // f[i][j][k] = max(f[i-1][g(j,k)]) + grid[j] + grid[k]
    n, m := len(grid), len(grid[0])
    f := make([]int, m*m)   // 当f[i][j] == 0 时表示该位置不可达
    f[0*m+m-1] = grid[0][0]+grid[0][m-1] + 1 // +1是防止第一个元素为0,因为0表示不可达,最后结果-1即可
    for i := 1; i < n; i++ {
        p := make([]int, m*m)
        for j := 0; j < min(i+1, m-1); j++ {
            for z := max(m-1-i, j+1); z < m; z++ {
                // 计算[j][z]的可考虑范围
                for jj := max(0, j-1); jj <= min(m-1, j+1); jj++ {
                    for zz := max(jj+1, z-1); zz <= min(m-1, z+1); zz++ {
                        if f[jj*m+zz] == 0 { continue }  // 这个位置不可达
                        p[j*m+z] = max(p[j*m+z], f[jj*m+zz]+grid[i][j]+grid[i][z])
                    }
                }
            }
        }
        f = p
    }
    _max := 0
    for i := 0; i < m-1; i++ {
        for j := i+1; j < m; j++ {
            _max = max(f[i*m+j], _max)
        }
    }
    return _max-1    // 减去添加的那个桃子
}
func max(a, b int) int { if a > b { return a }; return b }
func min(a, b int) int { if a < b { return a }; return b }

python3 解法, 执行用时: 1004 ms, 内存消耗: 55.5 MB, 提交时间: 2023-09-21 23:22:19

class Solution:
    def cherryPickup(self, grid: List[List[int]]) -> int:
        m, n = len(grid), len(grid[0])

        def getValue(i, j1, j2):
            return grid[i][j1] + grid[i][j2] if j1 != j2 else grid[i][j1]

        @lru_cache(None)
        def dfs(i, j1, j2):
            if i == m - 1:
                return getValue(i, j1, j2)
            
            best = 0
            for dj1 in [j1 - 1, j1, j1 + 1]:
                for dj2 in [j2 - 1, j2, j2 + 1]:
                    if 0 <= dj1 < n and 0 <= dj2 < n:
                        best = max(best, dfs(i + 1, dj1, dj2))

            return best + getValue(i, j1, j2)
        
        return dfs(0, 0, n - 1)

java 解法, 执行用时: 30 ms, 内存消耗: 41.8 MB, 提交时间: 2023-09-21 23:21:22

class Solution {
    public int cherryPickup(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        
        int[][] f = new int[n][n];
        int[][] g = new int[n][n];
        for (int i = 0; i < n; i++) {
            Arrays.fill(f[i], -1);
            Arrays.fill(g[i], -1);
        }
        f[0][n - 1] = grid[0][0] + grid[0][n - 1];
        for (int i = 1; i < m; ++i) {
            for (int j1 = 0; j1 < n; ++j1) {
                for (int j2 = 0; j2 < n; ++j2) {
                    int best = -1;
                    for (int dj1 = j1 - 1; dj1 <= j1 + 1; ++dj1) {
                        for (int dj2 = j2 - 1; dj2 <= j2 + 1; ++dj2) {
                            if (dj1 >= 0 && dj1 < n && dj2 >= 0 && dj2 < n && f[dj1][dj2] != -1) {
                                best = Math.max(best, f[dj1][dj2] + (j1 == j2 ? grid[i][j1] : grid[i][j1] + grid[i][j2]));
                            }
                        }
                    }
                    g[j1][j2] = best;
                }
            }
            int[][] temp = f;
            f = g;
            g = temp;
        }

        int ans = 0;
        for (int j1 = 0; j1 < n; ++j1) {
            for (int j2 = 0; j2 < n; ++j2) {
                ans = Math.max(ans, f[j1][j2]);
            }
        }
        return ans;

    }
}

cpp 解法, 执行用时: 112 ms, 内存消耗: 9.5 MB, 提交时间: 2023-09-21 23:21:05

/**
 * 设矩阵的长度为 m,宽度为 n,我们用 f[i][j1][j2] 表示当第一个机器人从 (0,0) 走到 (i,j1),
 * 第二个机器人从 (0,n−1) 走到 (i,j2),最多能收集的樱桃数目。
 *
 */
class Solution {
public:
    int cherryPickup(vector<vector<int>>& grid) {
        int m = grid.size();
        int n = grid[0].size();
        
        vector<vector<int>> f(n, vector<int>(n, -1)), g(n, vector<int>(n, -1));
        f[0][n - 1] = grid[0][0] + grid[0][n - 1];
        for (int i = 1; i < m; ++i) {
            for (int j1 = 0; j1 < n; ++j1) {
                for (int j2 = 0; j2 < n; ++j2) {
                    int best = -1;
                    for (int dj1 = j1 - 1; dj1 <= j1 + 1; ++dj1) {
                        for (int dj2 = j2 - 1; dj2 <= j2 + 1; ++dj2) {
                            if (dj1 >= 0 && dj1 < n && dj2 >= 0 && dj2 < n && f[dj1][dj2] != -1) {
                                best = max(best, f[dj1][dj2] + (j1 == j2 ? grid[i][j1] : grid[i][j1] + grid[i][j2]));
                            }
                        }
                    }
                    g[j1][j2] = best;
                }
            }
            swap(f, g);
        }

        int ans = 0;
        for (int j1 = 0; j1 < n; ++j1) {
            for (int j2 = 0; j2 < n; ++j2) {
                ans = max(ans, f[j1][j2]);
            }
        }
        return ans;
    }
};

上一题