欢迎各位勇者来到力扣城,城内设有烹饪锅供勇者制作料理,为自己恢复状态。
勇者背包内共有编号为 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
方法一:二进制枚举
我们注意到,料理的数量
每种料理都有两种选择:制作或者不制作。因此,我们可以使用一个长度为
我们在
枚举结束后,我们就可以得到最大的美味度。
时间复杂度
class Solution:
def perfectMenu(
self,
materials: List[int],
cookbooks: List[List[int]],
attribute: List[List[int]],
limit: int,
) -> int:
n = len(cookbooks)
ans = -1
for mask in range(1 << n):
a = b = 0
cnt = [0] * 5
for i in range(n):
if mask >> i & 1:
x, y = attribute[i]
a += x
b += y
for j, v in enumerate(cookbooks[i]):
cnt[j] += v
if b >= limit and ans < a and all(c <= d for c, d in zip(cnt, materials)):
ans = a
return ans
class Solution {
public int perfectMenu(int[] materials, int[][] cookbooks, int[][] attribute, int limit) {
int n = cookbooks.length;
int ans = -1;
for (int mask = 0; mask < 1 << n; ++mask) {
int a = 0, b = 0;
int[] cnt = new int[5];
for (int i = 0; i < n; ++i) {
if ((mask >> i & 1) == 1) {
int x = attribute[i][0];
int y = attribute[i][1];
a += x;
b += y;
for (int j = 0; j < cookbooks[i].length; ++j) {
cnt[j] += cookbooks[i][j];
}
}
}
boolean ok = true;
for (int i = 0; i < 5 && ok; ++i) {
ok = cnt[i] <= materials[i];
}
if (b >= limit && ans < a && ok) {
ans = a;
}
}
return ans;
}
}
class Solution {
public:
int perfectMenu(vector<int>& materials, vector<vector<int>>& cookbooks, vector<vector<int>>& attribute, int limit) {
int n = cookbooks.size();
int ans = -1;
for (int mask = 0; mask < 1 << n; ++mask) {
int a = 0, b = 0;
vector<int> cnt(5);
for (int i = 0; i < n; ++i) {
if (mask >> i & 1) {
int x = attribute[i][0];
int y = attribute[i][1];
a += x;
b += y;
for (int j = 0; j < cookbooks[i].size(); ++j) {
cnt[j] += cookbooks[i][j];
}
}
bool ok = true;
for (int i = 0; i < 5 && ok; ++i) {
ok = cnt[i] <= materials[i];
}
if (b >= limit && ans < a && ok) {
ans = a;
}
}
}
return ans;
}
};
func perfectMenu(materials []int, cookbooks [][]int, attribute [][]int, limit int) int {
n := len(cookbooks)
ans := -1
for mask := 0; mask < 1<<n; mask++ {
a, b := 0, 0
cnt := make([]int, 5)
for i := 0; i < n; i++ {
if mask>>i&1 == 1 {
x, y := attribute[i][0], attribute[i][1]
a += x
b += y
for j, v := range cookbooks[i] {
cnt[j] += v
}
}
ok := true
for i := 0; i < 5 && ok; i++ {
ok = cnt[i] <= materials[i]
}
if ok && b >= limit && ans < a {
ans = a
}
}
}
return ans
}
function perfectMenu(
materials: number[],
cookbooks: number[][],
attribute: number[][],
limit: number,
): number {
const n = cookbooks.length;
let ans = -1;
for (let mask = 0; mask < 1 << n; ++mask) {
let [a, b] = [0, 0];
const cnt: number[] = Array(5).fill(0);
for (let i = 0; i < n; ++i) {
if (((mask >> i) & 1) === 1) {
const [x, y] = attribute[i];
a += x;
b += y;
for (let j = 0; j < cookbooks[i].length; ++j) {
cnt[j] += cookbooks[i][j];
}
}
let ok = true;
for (let i = 0; i < 5 && ok; ++i) {
ok = cnt[i] <= materials[i];
}
if (b >= limit && ans < a && ok) {
ans = a;
}
}
}
return ans;
}