[LCP 51. 烹饪料理] 子集型回溯

Problem: LCP 51. 烹饪料理

文章目录

  • 思路
  • 案例分析
  • Code

思路

子集型回溯有两种解法

  1. 输入视角

    • 通过判断集合中的每一个元素 k,认为元素 k 被选入子集或不被选入子集,从而得到答案。其 dfs 形状是一个高度为 n 的二叉树。
    • 作为当前节点的元素 k 代表的是这次我处理的是第 k 的元素。
      在这里插入图片描述
  2. 答案视角

    • 每次判断在集合中选择哪一个元素,每次遍历中都枚举选择集合中的每一个数。但是注意由于顺序的问题,1->2和2->1实际上是一样的,所以我们每次从某一个元素 k 开始选择 k 及 k 以后的元素。
    • 作为当前节点的元素 k 代表的是这次我会遍历的元素有从 k 开始的剩余元素。
      ![在这里插入图片描述](https://img-blog.csdnimg.cn/d
  3. 两种解法的当前元素 k 看似写法很相似,结束条件也一致,然而代表的含义是完全不同的!
    如果不想明白用的是哪一种思考方式,就很非常容易将这两种写法杂糅在一起写。这样做不仅导致意义不明,难于理解,还会在 dfs 的过程中遍历多余节点。

案例分析

  1. 来看一个案例,答辩视角是在初次做题时写出的杂糅代码,其中混杂了两种写法(甚至写了注释)。重复的节点被遍历了,而且复盘的时候根本说不清楚自己每一步在做什么(很多次在做回溯的时候有的感觉,AC了但无法解释)。
  2. 作为对比下面写出了两种视角的正确写法,当读者辨别清楚二者的差距时应当能很清楚的理解子集型回溯到底应该做什么。

Code

答辩视角

  1. 在 dfs 之中使用了 for 循环,遍历元素 k 及之后的元素,这是典型的答案视角写法。可以看到注释中写了 do 和 don’t do 两种情况,这又是典型的输入视角写法。二者混杂在一起就合成了我们最终的三星答辩视角。
  2. 实际上错误在于没有将题目中的特别条件回溯的一般条件区分开来。题目中制作料理时有两种可能(可以做或不可以做),这是题目中特殊的的条件,也就是在某一步时,元素可能需要满足一定的条件才能加入集合。然而这和选和不选是完全不一样的! && 这和要不要继续递归也完全没有任何相干!
  3. 在输入视角中,对当前元素应当先看能不能做,如果能做就是两种选择(选或不选),如果不能做就是一种选择(不选)。
  4. 在答案视角中,每一个元素也应该看能不能做,如果能做就做,然后递归至子问题,如果不能做就不做,然后递归至子问题。
class Solution {int res = -1;int tmp = 0;public:int perfectMenu(vector<int>& materials, vector<vector<int>>& cookbooks, vector<vector<int>>& attribute, int limit) {dfs(0, limit, materials, cookbooks, attribute);return res;}void dfs(int k, int limit, vector<int>& materials, vector<vector<int>>& cookbooks, vector<vector<int>>& attribute) {if(k == attribute.size()) {if(limit <= 0) {res = max(res, tmp);}return;}for(int i = k; i < attribute.size(); i++) {int doable = true;for(int j = 0; j < cookbooks[i].size(); j++) {if(cookbooks[i][j] > materials[j]) doable = false;}// doif(doable) {for(int j = 0; j < cookbooks[i].size(); j++) {materials[j] -= cookbooks[i][j];}tmp += attribute[i][0];limit -= attribute[i][1];dfs(i + 1, limit, materials, cookbooks, attribute);for(int j = 0; j < cookbooks[i].size(); j++) {materials[j] += cookbooks[i][j];}tmp -= attribute[i][0];limit += attribute[i][1];}// don't dodfs(i + 1, limit, materials, cookbooks, attribute);}}
};

输入视角,选或不选

class Solution {int res = -1;int tmp = 0;public:int perfectMenu(vector<int>& materials, vector<vector<int>>& cookbooks, vector<vector<int>>& attribute, int limit) {dfs(0, limit, materials, cookbooks, attribute);return res;}void dfs(int k, int limit, vector<int>& materials, vector<vector<int>>& cookbooks, vector<vector<int>>& attribute) {if(k == attribute.size()) {if(limit <= 0) {res = max(res, tmp);}return;}int doable = true;for(int j = 0; j < cookbooks[k].size(); j++) {if(cookbooks[k][j] > materials[j]) doable = false;}// doif(doable) {for(int j = 0; j < cookbooks[k].size(); j++) {materials[j] -= cookbooks[k][j];}tmp += attribute[k][0];limit -= attribute[k][1];dfs(k + 1, limit, materials, cookbooks, attribute);for(int j = 0; j < cookbooks[k].size(); j++) {materials[j] += cookbooks[k][j];}tmp -= attribute[k][0];limit += attribute[k][1];}// don't dodfs(k + 1, limit, materials, cookbooks, attribute);}
};

答案视角,选择哪个

class Solution {int res = -1;int tmp = 0;public:int perfectMenu(vector<int>& materials, vector<vector<int>>& cookbooks, vector<vector<int>>& attribute, int limit) {dfs(0, limit, materials, cookbooks, attribute);return res;}void dfs(int k, int limit, vector<int>& materials, vector<vector<int>>& cookbooks, vector<vector<int>>& attribute) {if(k == attribute.size()) {cout << limit << endl;if(limit <= 0) {res = max(res, tmp);}return;}for(int i = k; i < attribute.size(); i++) {int doable = true;for(int j = 0; j < cookbooks[i].size(); j++) {if(cookbooks[i][j] > materials[j]) doable = false;}if(doable) {for(int j = 0; j < cookbooks[i].size(); j++) {materials[j] -= cookbooks[i][j];}tmp += attribute[i][0];limit -= attribute[i][1];}dfs(i + 1, limit, materials, cookbooks, attribute);if(doable) {for(int j = 0; j < cookbooks[i].size(); j++) {materials[j] += cookbooks[i][j];}tmp -= attribute[i][0];limit += attribute[i][1];}}}
};

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

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

相关文章

Unity Toggle与Toggle Group的妙用

Toggle与Toggle Group结合使用&#xff0c;妙处多多。 因为在同一Toggle Group内只有一个Toggle可以被选中&#xff0c;那么对于我们要创建单选按钮组、游戏的一些开关、暗夜模式、筛选不同显示内容等功能都非常好用。 比如我要实现通过点击不同按钮,从而筛选显示不同内容&am…

ES8生产实践——ES跨集群数据迁移方案测评

引言 场景需求 经常有小伙伴咨询如何将整个es集群数据如何迁移到另一个集群&#xff0c;其中往往会涉及到以下的问题&#xff1a; 跨es版本&#xff1a;老版本es集群数据迁移到新版本es集群。 跨集群&#xff1a;源数据和目的数据分布在两个不同的集群。 跨网络&#xff1a;两…

ch6文件操作和异常处理

os.listdir(path) 函数详解 功能: os.listdir(path) 函数用于返回指定目录下的所有文件和文件夹的名字列表&#xff0c;但不包括 . 和 ..。 参数: path: 要列出的目录的路径。 返回值: 一个包含目录下所有文件和文件夹名字的列表。 示例: import ospath "/home/u…

备战秋招(coding篇)

其中coding题目来源于师兄面试经验 1、链表的结构体反转链表 本质上就是一个构造函数 struct ListNode{int val_;ListNode* next_;ListNode() : val_(0), next_(NULL) {}ListNode(int x) : val_(x), next_(NULL) {}ListNode(int x, ListNode* next) : val_(x), next_(next) …

Crypto Gladiator League (CGL)

《加密角斗士》是一款完全链上游戏。所有角斗士、装备、代币等的生成过程都可以透明追溯。不可能被篡改或欺骗&#xff0c;使所有游戏物品都是真实资产。 CGL 现已升级为全链游戏平台和 Web3 游戏流量门户&#xff0c;通过多维度收集用户数据&#xff0c;并将数据应用于游戏中&…

【Java11下载、安装、部署指南】

oracle jdk11下载 oracle jdk所有版本归档【archive】下载地址&#xff1a; https://www.oracle.com/java/technologies/downloads/archive/ oracle jdk11下载地址&#xff1a; https://www.oracle.com/java/technologies/javase/jdk11-archive-downloads.html 配置或修改wi…

软件工程-第9章 软件工程项目管理概述

9.1 软件工程管理活动 9.2 软件规模、成本和进度估算 9.3 能力成熟度模型CMM 9.4 ISO 9000系列标准简介 9.5 CMM与ISO 9000系列标准的比较 9.6 本章小结

Matlab|基于多目标粒子群算法的配电网储能选址定容

目录 一、主要内容 二、主要流程 三、部分程序 四、程序结果 五、程序链接 一、主要内容 程序是对文章《基于多目标粒子群算法的配电网储能选址定容》的方法复现&#xff0c;具体内容如下&#xff1a; 以系统节点电压水平&#xff08;电网脆弱性&#xff09;、网络损耗以及…

数据库系统概论-第5章 数据库完整性

5.1 实体完整性 5.2 参照完整性 5.3 用户定义完整性 5.4 完整性约束命名子句 5.5 域中的完整性限制 5.6 断言 5.7 触发器 5.8 小结

Pytest自动化测试框架快速上手(超详细)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号&#xff1a;互联网杂货铺&#xff0c;回复1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;薪资嘎嘎涨 pytest是一个非常成熟的全功能的Python测试框架&#…

蓝桥杯单片机快速开发笔记——NE555测频

一、原理分析 NE555作为一种多功能集成电路&#xff0c;在信号发生和频率测量方面具有广泛的应用。通过合理配置和连接外部元件&#xff0c;可以实现不同类型的信号发生和频率测量功能。 原理&#xff1a; 信号发生器&#xff1a; NE555可以配置为多种不同的振荡器电路&#x…

【鸿蒙HarmonyOS开发笔记】通知模块之发布基础类型通知,内含如何将图片变成PixelMap对象

通知简介 应用可以通过通知接口发送通知消息&#xff0c;终端用户可以通过通知栏查看通知内容&#xff0c;也可以点击通知来打开应用。 通知常见的使用场景&#xff1a; 显示接收到的短消息、即时消息等。 显示应用的推送消息&#xff0c;如广告、版本更新等。 显示当前正…

基于cnn深度学习的yolov5+pyqt+分类+resnet+骨龄检测系统

往期热门博客项目回顾&#xff1a; 计算机视觉项目大集合 改进的yolo目标检测-测距测速 路径规划算法 图像去雨去雾目标检测测距项目 交通标志识别项目 yolo系列-重磅yolov9界面-最新的yolo 姿态识别-3d姿态识别 深度学习小白学习路线 YOLOv5与骨龄识别 YOLOv5&a…

极简生活|2024年让自己越来越好的18个极简好习惯

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 转眼间已经进入了2024年&#xff0c;新的一年&#xff0c;新的开始。 俗话说&#xff1a;百尺高台起于垒土&#xff0c;千里之堤毁于蚁穴。 好习惯积累的越多&#xff0c;坏习惯越来越少&#xff0c;我们的生活才能越…

【NLP笔记】预训练+微调范式之OpenAI Transformer、ELMo、ULM-FiT、Bert..

文章目录 OpenAI TransformerELMoULM-FiTBert基础结构Embedding预训练&微调 【原文链接】&#xff1a; BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding 【本文参考链接】 The Illustrated BERT, ELMo, and co. (How NLP Cracked Tra…

STL第一弹

2 STL初识 2.1 STL的诞生 长久以来&#xff0c;软件界一直希望建立一种可重复利用的东西 C的面向对象和泛型编程思想&#xff0c;目的就是复用性的提升 大多情况下&#xff0c;数据结构和算法都未能有一套标准,导致被迫从事大量重复工作为了建立数据结构和算法的一套标准,诞生…

Gradio官方文档

文章目录 构建您的第一个demo分享您的demo进度条受密码保护的应用程序The Interface class&#xff08;接口类&#xff09;Components Attributes&#xff08;组件属性&#xff09;多个输入和输出组件图像示例嵌套列表描述性内容手风琴中的附加输入The 4 Kinds of Gradio Inter…

蓝桥杯Python B组练习——完美的代价

一、题目 问题描述   回文串&#xff0c;是一种特殊的字符串&#xff0c;它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串&#xff0c;它不一定是回文的&#xff0c;请你计算最少的交换次数使得该串变成一个完美的回文串。   交换的定义是…

C语言-----冒泡排序

今天&#xff0c;让我们来学习一下C语言中一个简单的排序算法------冒泡排序。 什么是冒泡排序呢&#xff1f; 冒泡排序是C语言中一个可以将一个数组的内容按照升序或者降序进行重新排列的算法。简单来说&#xff0c;是一种排序的思维。 冒泡排序的核心思想&#xff1a;让同…

【手撸IM】通讯协议设计与实现

【手撸IM】专题由来&#xff1a;之前利用业余空闲时间写一个Java版Akka-Rpc&#xff0c;并且基于它写了一个分布式高性能文件服务&#xff0c;从反馈上来看&#xff0c;还是得到了一定的关注&#xff0c;甚至部分同学真的基于此直接抄作业和二开了。因此有了再进一步去手撸一个…