【LeetCode每日一题】——LCP 51.烹饪料理

news2024/11/17 3:46:02

文章目录

  • 一【题目类别】
  • 二【题目难度】
  • 三【题目编号】
  • 四【题目描述】
  • 五【题目示例】
  • 六【题目提示】
  • 七【解题思路】
  • 八【时间频度】
  • 九【代码实现】
  • 十【提交结果】

一【题目类别】

  • 回溯

二【题目难度】

  • 简单

三【题目编号】

  • LCP 51.烹饪料理

四【题目描述】

  • 欢迎各位勇者来到力扣城,城内设有烹饪锅供勇者制作料理,为自己恢复状态。
  • 勇者背包内共有编号为 0 ~ 4 的五种食材,其中 materials[j] 表示第 j 种食材的数量。通过这些食材可以制作若干料理,cookbooks[i][j] 表示制作第 i 种料理需要第 j 种食材的数量,而 attribute[i] = [x,y] 表示第 i 道料理的美味度 x 和饱腹感 y
  • 在饱腹感不小于 limit 的情况下,请返回勇者可获得的最大美味度。如果无法满足饱腹感要求,则返回 -1
  • 注意:
    • 每种料理只能制作一次。

五【题目示例】

  • 示例 1

    • 输入:materials = [3,2,4,1,2] cookbooks = [[1,1,0,1,2],[2,1,4,0,0],[3,2,4,1,0]] attribute = [[3,2],[2,4],[7,6]] limit = 5
    • 输出:7
    • 解释: 食材数量可以满足以下两种方案: 方案一:制作料理 0 和料理 1,可获得饱腹感 2+4、美味度 3+2 方案二:仅制作料理 2, 可饱腹感为 6、美味度为 7 因此在满足饱腹感的要求下,可获得最高美味度 7
  • 示例 2

    • 输入:materials = [10,10,10,10,10] cookbooks = [[1,1,1,1,1],[3,3,3,3,3],[10,10,10,10,10]] attribute = [[5,5],[6,6],[10,10]] limit = 1
    • 输出:11
    • 解释:通过制作料理 0 和 1,可满足饱腹感,并获得最高美味度 11

六【题目提示】

  • materials.length == 5
  • 1 <= cookbooks.length == attribute.length <= 8
  • cookbooks[i].length == 5
  • attribute[i].length == 2
  • 0 <= materials[i], cookbooks[i][j], attribute[i][j] <= 20
  • 1 <= limit <= 100

七【解题思路】

  • 该题是回溯算法的经典应用,其实我认为挺好理解,符合人的基本直觉,主要是要把题目读懂
  • 既然是回溯,我们就要确定何时结束递归,根据题目描述:“如果总饱腹感 >= 限制值,更新最大美味度”,所以这就是递归退出的条件,最后我们需要返回“最大美味度”
  • 那么核心递归过程呢?其实也很简单
    • 我们遍历每一道菜,对于每道菜我们首先需要检查这道菜是否已经做过了,如果做过了就跳过,否则继续下面的操作(题目要求每道菜只能做一次)
    • 然后再检查当前剩的食材的数量还能否支持做完这道菜,如果不能那就结束,回到上一个状态,否则继续下面的操作
    • 如果当前这道菜通过了所有检查,那么需要开始进行回溯操作
      • 标记这道菜已经做了
      • 继续做其它菜,并更新美味度和饱腹感
      • 回溯,恢复材料,并标记这道菜还未做
  • 可以发现,以上整个过程就是回溯算法的标准模板,只不过根据题目要求添加了一些检查而已
  • 最后返回回溯计算得到的“最大美味度”即可,具体细节可以参考下面的代码

八【时间频度】

  • 时间复杂度: O ( n m 2 n ) O(nm2^n) O(nm2n) n n n为菜品个数, m m m为材料的数量
  • 空间复杂度: O ( n ) O(n) O(n) n n n为菜品个数

九【代码实现】

  1. Java语言版
class Solution {

    // 初始化最大美味度为 -1(表示无法满足饱腹感条件时返回 -1)
    int maxRes = -1;

    public int perfectMenu(int[] materials, int[][] cookbooks, int[][] attribute, int limit) {
        // 记录每道菜是否做过
        boolean[] exists = new boolean[cookbooks.length];
        // 进行深度优先搜索
        dfs(materials, cookbooks, attribute, limit, exists, 0, 0);
        // 返回最大美味度
        return maxRes;
    }

    public void dfs(int[] materials, int[][] cookbooks, int[][] attribute, int limit, boolean[] exists, int sumx, int sumy) {
        // 如果总饱腹感 >= 限制值,更新最大美味度
        if (sumy >= limit) {
            maxRes = Math.max(sumx, maxRes);
        }
        // 获取菜谱总数
        int len = cookbooks.length;
        // 遍历每一道菜
        for (int i = 0; i < len; i++) {
            // 如果当前菜已经做过了,跳过
            if (exists[i]) {
                continue;
            }
            // 检查当前所剩的材料是否足够制作第 i 道料理
            int[] need = cookbooks[i];
            boolean canMake = true;
            for (int j = 0; j < need.length; j++) {
                if (materials[j] < need[j]) {
                    canMake = false;
                    break;
                }
            }
            // 可以制作这道菜
            if (canMake) {
                // 标记当前菜已经制作
                exists[i] = true;
                for (int j = 0; j < need.length; j++) {
                    materials[j] -= need[j];
                }
                // 递归调用,继续制作其它菜,并更新美味度和饱腹感
                dfs(materials, cookbooks, attribute, limit, exists, sumx + attribute[i][0], sumy + attribute[i][1]);
                // 回溯:恢复材料,并标记这道菜为未制作
                for (int j = 0; j < need.length; j++) {
                    materials[j] += need[j];
                }
                exists[i] = false;
            }
        }
    }

}
  1. Python语言版
class Solution:

    def __init__(self):
        # 初始化最大美味度为 -1(表示无法满足饱腹感条件时返回 -1)
        self.maxRes = -1

    def perfectMenu(self, materials: List[int], cookbooks: List[List[int]], attribute: List[List[int]], limit: int) -> int:
        # 记录每道菜是否做过
        exists = [False] * len(cookbooks)
        # 进行深度优先搜索
        self.dfs(materials, cookbooks, attribute, limit, exists, 0, 0)
        # 返回最大美味度
        return self.maxRes

    def dfs(self, materials, cookbooks, attribute, limit, exists, sumx, sumy):
        """
        深度优先搜索函数
        :param materials: List[int] 当前剩余的材料数量
        :param cookbooks: List[List[int]] 每道菜需要的材料数量
        :param attribute: List[List[int]] 每道菜的美味度和饱腹感
        :param limit: int 最小饱腹感限制
        :param exists: List[bool] 当前的菜是否已经制作
        :param sumx: int 当前总美味度
        :param sumy: int 当前总饱腹感
        """
        # 如果总饱腹感 >= 限制值,更新最大美味度
        if sumy >= limit:
            self.maxRes = max(self.maxRes, sumx)
        # 获取菜谱总数
        len_cookbooks = len(cookbooks)
        # 遍历每一道菜
        for i in range(len_cookbooks):
            # 如果当前菜已经做过了,跳过
            if exists[i]:
                continue
            # 检查当前所剩的材料是否足够制作第 i 道料理
            need = cookbooks[i]
            can_make = True
            for j in range(len(need)):
                if materials[j] < need[j]:
                    can_make = False
                    break
            # 可以制作这道菜
            if can_make:
                # 标记当前菜已经制作
                exists[i] = True
                # 减去所需的材料
                for j in range(len(need)):
                    materials[j] -= need[j]
                # 递归调用,继续制作其它菜,并更新美味度和饱腹感
                self.dfs(materials, cookbooks, attribute, limit, exists, sumx + attribute[i][0], sumy + attribute[i][1])
                # 回溯:恢复材料,并标记这道菜为未制作
                for j in range(len(need)):
                    materials[j] += need[j]
                exists[i] = False
  1. C语言版
// 初始化最大美味度为 -1(表示无法满足饱腹感条件时返回 -1)
int maxRes = -1;

void dfs(int * materials, int materialsSize, int** cookbooks, int cookbooksSize, int** attribute, int limit, bool* exists, int sumx, int sumy)
{
    // 如果总饱腹感 >= 限制值,更新最大美味度
    if (sumy >= limit)
    {
        if (sumx > maxRes) {
            maxRes = sumx;
        }
    }
    // 遍历每一道菜
    for (int i = 0; i < cookbooksSize; i++)
    {
        // 如果当前菜已经做过了,跳过
        if (exists[i])
        {
            continue;
        }
        // 检查当前所剩的材料是否足够制作第 i 道料理
        bool canMake = true;
        for (int j = 0;j < materialsSize; j++)
        {
            if (materials[j] < cookbooks[i][j])
            {
                canMake = false;
                break;
            }
        }
        // 可以制作这道菜
        if (canMake)
        {
            // 标记当前菜已经制作
            exists[i] = true;
            for (int j = 0; j < materialsSize; j++)
            {
                materials[j] -= cookbooks[i][j];
            }
            // 递归调用,继续制作其它菜,并更新美味度和饱腹感
            dfs(materials, materialsSize, cookbooks, cookbooksSize, attribute, limit, exists, sumx + attribute[i][0], sumy + attribute[i][1]);
            // 回溯:恢复材料,并标记这道菜为未制作
            for (int j = 0; j < materialsSize; j++)
            {
                materials[j] += cookbooks[i][j];
            }
            exists[i] = false;
        }
    }
}

int perfectMenu(int* materials, int materialsSize, int** cookbooks, int cookbooksSize, int* cookbooksColSize, int** attribute, int attributeSize, int* attributeColSize, int limit)
{
    // 初始化最大美味度为 -1(表示无法满足饱腹感条件时返回 -1)
    maxRes = -1;
    // 记录每道菜是否做过
    bool* exists = (bool*)malloc(cookbooksSize * sizeof(bool));
    for (int i = 0; i < cookbooksSize; i++) {
        exists[i] = false;
    }
    // 进行深度优先搜索
    dfs(materials, materialsSize, cookbooks, cookbooksSize, attribute, limit, exists, 0, 0);
    // 释放资源
    free(exists);
    // 返回最大美味度
    return maxRes;
}

十【提交结果】

  1. Java语言版
    在这里插入图片描述

  2. Python语言版
    在这里插入图片描述

  3. C语言版
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【工具分享】NoWay勒索病毒解密工具

前言 NoWay勒索软件首次出现在2023年&#xff0c;并迅速引起了网络安全领域的关注。它是一种典型的加密勒索软件&#xff0c;主要通过恶意电子邮件附件或不安全的下载链接传播。一旦成功感染系统&#xff0c;NoWay会加密受害者的文件&#xff0c;并要求支付赎金以恢复文件访问…

Redis(初步认识和安装)

初识Redis 认识NoSQLSQL结构化&#xff1a;structure关联的&#xff1a;RelationalSQL查询ACID NoSQL非结构化无关联的非SQLBASE 认识Redis安装Redis 认识NoSQL SQL和NoSQL比较 SQL 结构化&#xff1a;structure 数据库中表的字段都有固定的结构 关联的&#xff1a;Relati…

【c语言数据结构】栈的详解! 超级详细!(模拟实现,OJ练习题)

栈的概念&#xff1a; 栈&#xff1a;像是一种容器&#xff0c;东西只能从一个地方进&#xff0c;一个地方出&#xff0c;且后进先出&#xff01;这是其和队列&#xff08;先进先出&#xff0c;像排队一样&#xff0c;先到先得&#xff09;的本质区别 ⼀种特殊的线性表&#…

“JY901传感器“学习笔记

目录 一、产品概述 二、产品功能介绍 2.1、轴向说明 2.2、模块校准 2.3、姿态角 2.4、大地坐标系、地心地固坐标系、站心坐标系 三、参考文献 一、产品概述 模块集成高精度的陀螺仪、加速度计、地磁场传感器&#xff0c;采用高性能的微处理器和先进的动力解算与卡尔曼动…

两种不同方式实现交换机路由器的登录Console+Telnet的实现

一、背景及原理 1.Telnet 作为一种远程登录协议,1969年发明诞生于美国国防部高级研究计划局网络工作小组的研究员,Tenlet的出现为后续相关技术的发展奠定了基础。 2.Telnet通常用于远程登录应用中,对本地和远端进行网络设备配置、监控、维护,可以通过Telnet方式在一台设备…

博睿数据受邀亮相NebulaGraph Meetup北京站

9 月 21 日&#xff0c;北京站 nMeetup 如期而至&#xff0c;一场以 GraphRAG 和人工智能技术融合为主题的开发者聚会&#xff0c;在金秋的首都拉开帷幕。8 位讲师和 140 多位来自五湖四海的行业伙伴们相聚一堂&#xff0c;共同探讨 GraphRAG & AI 的最新发展和应用实践&am…

卷轴模式:一种新型的电子商务营销策略

随着电子商务行业的蓬勃发展&#xff0c;各类创新营销策略层出不穷&#xff0c;旨在吸引更多消费者并提升销售额。在这之中&#xff0c;卷轴模式以其独特的优势和可观的收益逐渐受到业界renxb001的关注。本文将深入探讨卷轴模式的概念、优势、应用场景以及如何参与其中。 卷轴…

关联式容器——map与set

map与set map与set的使用序列式容器与关联式容器概念序列式容器 (Sequence Containers)常见的序列式容器&#xff1a; 关联式容器 (Associative Containers)常见的关联式容器&#xff1a; set的定义与使用set类的介绍set的构造和迭代器set的增删查&#xff08;无改&#xff09;…

Ego微商小程序项目实战4.0【环境搭建】

✨博客主页&#xff1a; https://blog.csdn.net/m0_63815035?typeblog &#x1f497;《博客内容》&#xff1a;.NET、Java.测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识 &#x1f4e2;博客专栏&#xff1a; https://blog.csdn.net/m0_63815035/cat…

自动化测试框架集成:将Selenium集成到pytest与unittest中

目录 引言 一、Selenium简介 二、Selenium与pytest的集成 1. 安装pytest和Selenium 2. 编写测试用例 3. 运行测试 三、Selenium与unittest的集成 1. 编写测试类 2. 运行测试 四、Selenium自动化测试的最佳实践 1. 使用Page Object模式 2. 合理利用等待机制 3. 跨浏…

vioovi视与视标准工时工具与ECRS工时分析软件:精益生产的新纪元

在当今快速变化的市场环境中&#xff0c;企业面临着前所未有的挑战&#xff0c;其中成本控制与效率提升成为制约其发展的关键因素。传统的标准工时工具在应对这些挑战时显得力不从心&#xff0c;其局限性日益凸显。而vioovi视与视标准工时工具的出现&#xff0c;则为企业实现精…

西门子触摸屏下载时提示缺少面板映像的解决方法汇总

西门子触摸屏下载时提示缺少面板映像的解决方法汇总 使用V15/V15.1/V16/V17/V18/V19下载精智(Comfort)系列屏的项目时有时会提示“由于缺少面板映像,下载失败。请安装缺少的面板映像”,造成上述异常的主要原因是V15/V15.1/V16/V17/V18/V19的软件缺少对应的映像文件。常见问题…

《Linux从小白到高手》开篇:脱胎换骨之为什么要深度学习Linux?

List item 这一篇字数比较多&#xff0c;可能会比较枯燥。但是&#xff0c;如果你想学习Linux或者你想进一步提升自己的Linux专业水平&#xff0c;那么&#xff0c;还是请你坚持看完。这倒不是说文笔有多好&#xff0c;而是作为一个学习并使用了Linux 十多年的老司机&#xff…

PHP Swoole 基本使用

背景 在项目中&#xff0c;我们使用了PHP语言&#xff0c;但由于存在长耗时的任务&#xff0c;所以需要服务器端异步响应。为了实现异步响应&#xff0c;我们有多种方案可选&#xff0c;包括MQ&#xff08;消息队列&#xff09;、fsocket&#xff08;文件套接字&#xff09;、…

【Redis】渐进式遍历 数据库管理命令 RESP协议

目录 渐进式遍历 scan 数据库管理命令 切换数据库 获取当前数据库key的个数 删除当前数据库所有的key 删除所有数据库中所有的key RESP协议 渐进式遍历 Redis使用scan命令进行渐进式遍历键&#xff0c;进而解决直接使用keys获取键时可能出现的阻塞问题&#xff08;因为…

多旋翼无人机光伏发电站吊运技术详解

随着清洁能源技术的快速发展&#xff0c;光伏发电站作为可再生能源的重要组成部分&#xff0c;其建设与维护对效率、安全性和成本控制的要求日益提高。多旋翼无人机光伏发电站吊运技术应运而生&#xff0c;该技术利用多旋翼无人机强大的垂直起降能力、灵活的飞行控制以及高效的…

CSS中的字体样式、文本样式、列表样式以及背景和渐变

一、字体样式和文本样式 1.span标签 span标签的作用&#xff1a;能让某几个文字或者是词语凸显出来 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-…

【深度学习基础模型】门控循环单元 (Gated Recurrent Units, GRU)详细理解并附实现代码。

【深度学习基础模型】门控循环单元 (Gated Recurrent Units, GRU) 【深度学习基础模型】门控循环单元 (Gated Recurrent Units, GRU) 文章目录 【深度学习基础模型】门控循环单元 (Gated Recurrent Units, GRU)1.门控循环单元 (Gated Recurrent Units, GRU) 原理详解1.1 GRU 概…

一个任务的一辈子

总览 孕育&#xff1a;这一步是生命的起源&#xff0c;对应"任务"就是&#xff1a;申办人因为办理业务而发起一个流程。这是任务产生的摇篮。 任务的使命就是为了完成业务;生产&#xff1a;这是新生命产生的过程&#xff0c;对应"任务"就是&#xff1a;任务…

IT运维挑战与对策:构建高效一体化运维管理体系

在当今数字化时代&#xff0c;IT运维作为企业运营的核心支撑&#xff0c;其重要性不言而喻。然而&#xff0c;随着业务规模的扩大和技术的不断革新&#xff0c;IT运维团队面临着前所未有的挑战。本文旨在深度剖析当前IT运维中存在的主要问题&#xff0c;并探索一体化解决方案&a…