Cherry Pickup解题心得

Cherry Pickup解题心得

来源:https://leetcode.com/problems/cherry-pickup/description/

题目复述

输入一个n x n大小的地图,地图中的每个位置值包含三种值(-1, 0, 1),其中:

-1:代表不允许通过
0:代表可以通过
1:代表可以通过,而且路上有个Cherry(樱桃)

例如,输入:

 Input: grid =
[[0, 1, -1],
 [1, 0, -1],
 [1, 1,  1]]

要求从[0, 0]出发到[n-1, n-1],要求只能向右或向下走,一路上收集樱桃,一个单位里的樱桃只能取走一次,如果取走则再次通过则为空;当到达[n-1, n-1]后再向左向上走回[0, 0],一路上同样收集樱桃
输出,求该过程(即从[0, 0]到[n-1, n-1],从[n-1, n-1]到[0, 0])最多可以获得多少樱桃
例如上输出的答案输出:

Output: 5

解题思路

  1. 最初思考的是实验动态规划计算,从[0, 0]到[n-1, n-1]的最大樱桃值,同时更新地图上经过有樱桃的位置为0,再从[n-1, n-1]到[0, 0]做一次一样的动态规划算法,则两次最优解的和为总体最优
  2. 结果发现这总单单的将两个最优解和是无法求到最优的解,在leetcode里看他人的解题思路,发现需要将求一条路最大值的动态规划解题思路转变,转变为同时求两条路最大和的动态规划过程:
    dpk[x1][x2]:k[0,0][x1, kx1][x2, kx2]dpk[x1][x2]=max(dpk1[x1][x2], dpk1[x11][x2], dpk1[x1][x21], dpk1[x11][x21])
  3. 这个过程很抽象,特别是 dpk[x1][x2] 的含义,有点难以理解,可能需要画图进行进一步的理解;总之算法实现时实际使用的是dp[x1][x2],k是多次循环覆盖的过程
  4. 多看看下面这段三层循环的代码理解,核心表示的就是上面状态转移方程的含义,每个k循环中的dp的含义代表了 dpk ,然后是用当前更新的 dpk 覆盖前一个循环的 dpk1 的值:
for (int k = 0; k <= maxLen; k++) {
            int maxt = min(k, n-1);
            for (int x1 = maxt; x1 >= 0; x1--)
                for (int x2 = maxt; x2 >= 0; x2--) {
                    int y1 = k - x1;
                    int y2 = k - x2;
                    if (y1 > n || y2 > n) continue;
                    if (grid[x1][y1] < 0 || grid[x2][y2] < 0) {
                        dp[x1][x2] = -1;
                        continue;
                    }
                    int cherry = grid[x1][y1] + grid[x2][y2];
                    if (x1-1 >= 0) dp[x1][x2] = max(dp[x1][x2], dp[x1-1][x2]);
                    if (x2-1 >= 0) dp[x1][x2] = max(dp[x1][x2], dp[x1][x2-1]);
                    if (x1-1 >= 0 && x2-1 >= 0) dp[x1][x2] = max(dp[x1][x2], dp[x1-1][x2-1]);

                    if (dp[x1][x2] == -1) continue;
                    if (x1 != x2) dp[x1][x2] += cherry;
                    else dp[x1][x2] += grid[x1][y1];

                }
        }


  1. 这里就不贴详细代码了,具体可以看下面我的这个代码连接:

传送门:https://github.com/zhanzongyuan/leetcode/blob/master/741_Cherry%20Pickup.cpp

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值