一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情。
每日刷题 2021.04.16
- leetcode原题链接:leetcode-cn.com/contest/sea…
- 难度:简单
- 方法:dfs
题目
- 欢迎各位勇者来到力扣城,城内设有烹饪锅供勇者制作料理,为自己恢复状态。
- 勇者背包内共有编号为
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,可满足饱腹感,并获得最高美味度 1
提示
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
解题思路
- 类似的题目(选与不选的思想)1601. 最多可达成的换楼请求数目
题意
- 给你每个食材的个数,记为
materials
数组;给你一个菜谱cookbooks
,上面记录了cookbooks.length
个食谱,每个食谱都提供了其需要哪些食材;对应的每个食谱都存在一个相对应的美味值和饱腹值 - 现在问你,如何在满足饱腹值的情况下,使美味值最大。需要注意的情况:如何不能满足饱腹值,就返回
-1
思想
- 常规的分析:对于每一个食谱来说,均可以与任意的一个食谱进行匹配组合,并且这个组合不一定是
2
个或者3
个,因此不能使用二分查找和双指针来进行查找。 - 从而就想到了使用
dfs
来实现,对于递归的调用,那么我们可以遍历每一个节点:选择和不选择的多重组合,从而来覆盖所有的情况,找出满足饱腹感后,最大的美味值。 - 三步走
dfs
分析- 第一步:确定返回值和参数。
void
返回值,参数=>
当前食谱下标,美味值,饱腹值 - 第二步:确定终止条件。 当前食谱的下标
== len
,说明已经遍历过了最后一个食谱了,没有可以进行遍历的食谱了,就返回。 - 第三步:确定单层的循环逻辑。1.不选择当前的食谱 2.选择当前的食谱(选择的话,需要先写上选择当前食谱需要执行的操作,再进行
dfs
下一个状态)记得:最后返回到当前层的时候,一定要将状态还原回去,不要影响下一次操作。
- 第一步:确定返回值和参数。
AC
代码
var perfectMenu = function(materials, cookbooks, attribute, limit) {
// 参数:食谱,做还是不做
let len = cookbooks.length;
let book = cookbooks,me = materials,att = attribute;
let max = -1;
function dfs(cur, pertty, lim) {
if (cur >= len){
if(lim >= limit){
max = max < pertty ? pertty : max;
}
return;
}
// 不做当前的料理
dfs(cur + 1, pertty, lim);
// 做当前的料理
// 书写选择的逻辑
// 判断是否所有的食材都存在
let lenB = book[cur].length;
// console.log('BBB', lenB)
let flag = true;
for(let i = 0; i < lenB; i++) {
if(me[i] < book[cur][i]) {
flag = false;
break;
}
}
if(flag){
for(let i = 0; i < lenB; i++) {
me[i] = me[i] - book[cur][i];
}
// 如果食材都齐全,就计算饱腹值和美味值
dfs(cur + 1, pertty + att[cur][0], lim + att[cur][1])
for(let i = 0; i < lenB; i++) {
me[i] = me[i] + book[cur][i];
}
}
}
// 美味值
dfs(0, 0, 0)
return max;
};
总结
- 今天很开心,自己能够完整的写出来这个题目解法,并且在思路上还是实现上,都有了进一步的了解和分析。