记一次动态规划的采坑之旅, 741摘樱桃 https://leetcode.cn/problems/cherry-pickup/description/

首次看题目时,发现是困难。立马想到了,动态规划。

再看题目, 摘樱桃,还要返回摘两次,求摘最多的樱桃。

大脑第一反应就是:

先使用动态规划,找到 0 0 到 n-1 n-1处走过的最大樱桃, 并记录路径path。

然后根据路径path,将摘过的樱桃置为0,表示已经被摘过了。 然后再次摘樱桃。

两次摘过的樱桃之和就是目标的结果。

嗯,应该是,那就开写。

func cherryPickup(grid [][]int) int {
    ans := 0

    n := len(grid)
    dp := make([][]int, 0)
    for i := 0; i < n; i++ {
        dp = append(dp, make([]int, n))
    }

    // 1 表示上一个路径是 上
    // 2 表示上一个路径是 左
    path := make([][]int, 0)
    for i := 0; i < n; i++ {
        path = append(path, make([]int, n))
    }

    // 记录首次dp的轨迹,开始第一次摘
    for i := 0; i < len(grid); i++ {
        for j := 0; j < len(grid[0]); j++ {
            if i == 0 && j == 0 {
                dp[0][0] = grid[0][0]
                continue
            }
            if grid[i][j] == -1 {
                dp[i][j] = -1
                continue
            }

            if (i - 1 < 0 || grid[i-1][j] == -1 || dp[i-1][j] == -1) && (j - 1 < 0 || grid[i][j-1] == -1 || dp[i][j-1] == -1) {
                dp[i][j] = -1
                continue
            }

            if i - 1 < 0 || grid[i-1][j] == -1 || dp[i-1][j] == -1 {
                dp[i][j] = dp[i][j-1] + grid[i][j]
                path[i][j] = 2
                continue
            }
            if j - 1 < 0 || grid[i][j-1] == -1 || dp[i][j-1] == -1 {
                dp[i][j] = dp[i-1][j] + grid[i][j]
                path[i][j] = 1
                continue
            }
           
            if dp[i][j-1] > dp[i-1][j] {
                path[i][j] = 2
                dp[i][j] = dp[i][j-1] + grid[i][j]
            } else {
                path[i][j] = 1
                dp[i][j] = dp[i-1][j] + grid[i][j]
            }
        }
    }

    ans += dp[n-1][n-1]
    if ans == -1 {
        return 0
    }
    // 回溯路径, 清理已经被摘过的樱桃
    ii, jj := n-1, n-1
    for path[ii][jj] != 0 {
        grid[ii][jj] = 0
        if path[ii][jj] == 1 {
            ii--
        } else {
            jj--
        }
    }
    // 第二次摘樱桃
    grid[0][0] = 0
    dp = make([][]int, 0)
    for i := 0; i < n; i++ {
        dp = append(dp, make([]int, n))
    }
     for i := 0; i < len(grid); i++ {
        for j := 0; j < len(grid[0]); j++ {
            if i == 0 && j == 0 {
                dp[0][0] = grid[0][0]
                continue
            }
            if grid[i][j] == -1 {
                dp[i][j] = -1
                continue
            }

            if (i - 1 < 0 || grid[i-1][j] == -1 || dp[i-1][j] == -1) && (j - 1 < 0 || grid[i][j-1] == -1 || dp[i][j-1] == -1) {
                dp[i][j] = -1
                continue
            }

            if i - 1 < 0 || grid[i-1][j] == -1 || dp[i-1][j] == -1 {
                dp[i][j] = dp[i][j-1] + grid[i][j]
                path[i][j] = 2
                continue
            }
            if j - 1 < 0 || grid[i][j-1] == -1 || dp[i][j-1] == -1 {
                dp[i][j] = dp[i-1][j] + grid[i][j]
                path[i][j] = 1
                continue
            }
           
            if dp[i][j-1] > dp[i-1][j] {
                path[i][j] = 2
                dp[i][j] = dp[i][j-1] + grid[i][j]
            } else {
                path[i][j] = 1
                dp[i][j] = dp[i-1][j] + grid[i][j]
            }
        }
    }
    // 将两次摘的樱桃数相加
    return ans + dp[n-1][n-1]
}

最后发现通过 53/59 , 差一点点点点。 其实差很多。

通过研究这个未通过的案例, 发现我虽然2次摘樱桃都是最大值, 但并不能证明最终采摘的樱桃数是最大的。

最后瞄了一眼答案, 来回摘2次樱桃数最多,又不能重复摘, 那找两个人同时摘不就好了吗。 

附上leetcode标准答案

func cherryPickup(grid [][]int) int {
    n := len(grid)
    f := make([][][]int, n*2-1)
    for i := range f {
        f[i] = make([][]int, n)
        for j := range f[i] {
            f[i][j] = make([]int, n)
            for k := range f[i][j] {
                f[i][j][k] = math.MinInt32
            }
        }
    }
    f[0][0][0] = grid[0][0]
    for k := 1; k < n*2-1; k++ {
        for x1 := max(k-n+1, 0); x1 <= min(k, n-1); x1++ {
            y1 := k - x1
            if grid[x1][y1] == -1 {
                continue
            }
            for x2 := x1; x2 <= min(k, n-1); x2++ {
                y2 := k - x2
                if grid[x2][y2] == -1 {
                    continue
                }
                res := f[k-1][x1][x2] // 都往右
                if x1 > 0 {
                    res = max(res, f[k-1][x1-1][x2]) // 往下,往右
                }
                if x2 > 0 {
                    res = max(res, f[k-1][x1][x2-1]) // 往右,往下
                }
                if x1 > 0 && x2 > 0 {
                    res = max(res, f[k-1][x1-1][x2-1]) // 都往下
                }
                res += grid[x1][y1]
                if x2 != x1 { // 避免重复摘同一个樱桃
                    res += grid[x2][y2]
                }
                f[k][x1][x2] = res
            }
        }
    }
    return max(f[n*2-2][n-1][n-1], 0)
}

func min(a, b int) int {
    if a > b {
        return b
    }
    return a
}

func max(a, b int) int {
    if b > a {
        return b
    }
    return a
}

作者:力扣官方题解
链接:https://leetcode.cn/problems/cherry-pickup/solutions/1656418/zhai-ying-tao-by-leetcode-solution-1h3k/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/596490.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【码银送书第十九期】《图算法:行业应用与实践》

作者&#xff1a;嬴图团队 01 前言 在当今工业领域&#xff0c;图思维方式与图数据技术的应用日益广泛&#xff0c;成为图数据探索、挖掘与应用的坚实基础。本文旨在分享嬴图团队在算法实践应用中的宝贵经验与深刻思考&#xff0c;不仅促进业界爱好者之间的交流&#xff0c;…

AI不只是技术,更是一种思维方式

一、AI思维 1.个人&#xff1a;提升自己的综合能力&#xff0c;成为一名懂技术、懂设计、懂硬件、懂市场运营等知识的综合型人才 2.数据&#xff1a;从全局视角看数据流向&#xff0c;挖掘数据价值 3.产品&#xff1a;运用新技术&#xff0c;发掘新需求点&#xff0c;探索产…

AI智体的分级:从基于规则到基于LLM

摘要&#xff1a; AI智体被定义为感知环境、做出决策和采取行动的人工实体。受SAE&#xff08;汽车工程师学会&#xff09;自动驾驶6个级别的启发&#xff0c;AI智体也根据效用和强度进行分类&#xff0c;分为以下几个级别&#xff1a;L0——无AI&#xff0c;有工具&#xff0…

马常旭新歌《如愿》:音乐界的“旭日”再现

在这个春暖花开的季节&#xff0c;音乐界又迎来了一股清新的“旭日”气息。是的&#xff0c;就在2024年4月17日&#xff0c;马常旭的新歌《如愿》&#xff08;旭日版&#xff09;在网易云音乐上线了&#xff01;一年的等待&#xff0c;终于迎来了他的音乐回归&#xff0c;给我们…

C语言知识点补充——ASCLL码表

1、ASCLL码表 ASCII码表&#xff08;American Standard Code for Information Interchange&#xff09;是一种用于将字符编码为数字的标准。它定义了128个字符的编码方式&#xff0c;包括数字、字母、标点符号和控制字符等。每个字符都对应一个唯一的7位或8位二进制数 2、Ascl…

贪吃蛇项目(小白保姆级教程)

游戏介绍 游戏背景&#xff1a; 贪吃蛇游戏是经典的游戏项目之一&#xff0c;也是很简单的小游戏 实现背景&#xff1a; 这里我们是基于32位的Win32_API进行实现的 需要的知识点&#xff1a; C语言函数、枚举、结构体、动态内存管理、预处理指令、链表、Win32_API等 适合人群&a…

java中的字符串(String)常量池理解

下面创建String对象的方式一样吗&#xff1f; 上述程序创建对象类似&#xff0c;为什么s1和s2引用对象一样&#xff0c;但是s3和s4不一样呢&#xff1f; 在java程序中&#xff0c;许多基本类型的字面常量会经常用到&#xff0c;例如2,3.11&#xff0c;“hyy”等。为了提升程序…

C语言动态内存管理malloc、calloc、realloc、free函数、内存泄漏、动态内存开辟的位置等的介绍

文章目录 前言一、为什么存在动态内存管理二、动态内存函数的介绍1. malloc函数2. 内存泄漏3. 动态内存开辟位置4. free函数5. calloc 函数6. realloc 函数7. realloc 传空指针 总结 前言 C语言动态内存管理malloc、calloc、realloc、free函数、内存泄漏、动态内存开辟的位置等…

25.哀家要长脑子了---哈希表

1.525. 连续数组 - 力扣&#xff08;LeetCode&#xff09; 在我对通义千问的一番折磨下&#xff0c;终于弄清楚一点点了。哈希表存储前缀和数组值 用一个counter来记录nums中0、1数量差值的变化。 哈希表map存储某个特定的counter值首次出现的位置。counter的计算&#xff1a;…

【LeetCode 121】买卖股票的最佳时机

思路 思路&#xff1a; 所谓代码的复杂性来源于业务的复杂性&#xff0c;如果能够想清楚业务实现逻辑&#xff0c;就能够轻松写出代码&#xff1b; 假设当前是第i天&#xff0c;如何在第i天赚到最多的钱&#xff1f;需要在第i天之前以最低价买入股票&#xff1b; 所以需要求…

13 【PS作图】人物绘画理论-脸型

三庭五眼 三庭&#xff1a;脸的长度比例 &#xff08;1&#xff09;发际线到眉毛 &#xff08;2&#xff09;眉毛到鼻底 &#xff08;3&#xff09;鼻底到下巴 三个部分大致为三等分 五眼&#xff1a;脸的宽度比例 以眼睛长度为单位&#xff0c;把脸的宽度分成五等分&#x…

[极客大挑战 2019]PHP

1.通过目录扫描找到它的备份文件&#xff0c;这里的备份文件是它的源码。 2.源码当中涉及到的关键点就是魔术函数以及序列化与反序列化。 我们提交的select参数会被进行反序列化&#xff0c;我们要构造符合输出flag条件的序列化数据。 但是&#xff0c;这里要注意的就是我们提…

求解亲和数

【问题描述】 古希腊数学家毕达哥拉斯在自然数研究中发现&#xff0c;220的所有真约数&#xff08;即不是自身 的约数&#xff09;之和为&#xff1a; 1245101120224455110284。而284的所有真约数为1、2、4、71、142&#xff0c;加起来恰好为220。人 们对这样的数感到很惊奇&am…

五种主流数据库:窗口函数

SQL 窗口函数为在线分析系统&#xff08;OLAP&#xff09;和商业智能&#xff08;BI&#xff09;提供了复杂分析和报表统计的功能&#xff0c;例如产品的累计销量统计、分类排名、同比/环比分析等。这些功能通常很难通过聚合函数和分组操作来实现。 本文比较了五种主流数据库实…

嵌入式学习67-C++(多线程,自定义信号合槽,串口通信)

知识零碎&#xff1a; QmessageBox 报错提示框 GPS传感器获取到的 经纬度信息并不是真实的物理坐标&#xff0c;还需要转换 signals&#xff1a; …

【JAVA入门】Day03 - 数组

【JAVA入门】Day03 - 数组 文章目录 【JAVA入门】Day03 - 数组一、数组的概念二、数组的定义2.1 数组的静态初始化2.2 数组的地址值2.3 数组元素的访问2.4 数组遍历2.5 数组的动态初始化2.6 数组的常见操作2.7 数组的内存分配2.7.1 Java内存分配2.7.2 数组的内存图 一、数组的概…

234234235

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

周刊是聪明人筛选优质知识的聪明手段!

这是一个信息过载的时代&#xff0c;也是一个信息匮乏的时代。 这种矛盾的现象在 Python 编程语言上的表现非常明显。 它是常年高居编程语言排行榜的最流行语言之一&#xff0c;在国外发展得如火如荼&#xff0c;开发者、项目、文章、播客、会议活动等相关信息如海如潮。 但…

对XYctf的一些总结

对XYctf的一些总结 WEB 1.http请求头字段 此次比赛中出现的&#xff1a; X-Forwarded-For/Client-ip&#xff1a;修改来源ip via&#xff1a;修改代理服务器 还有一些常见的字段&#xff1a; GET&#xff1a;此方法用于请求指定的资源。GET请求应该安全且幂等&#xff0c…

QTday1

1、QT思维导图 2、自由发挥应用场景&#xff0c;实现登录 #include "mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent) {this->resize(642,493);this->setFixedSize(642,493);this->setWindowIcon(QIcon("D:/QTText/pictrue/qq.png…