[LeetCode] 1298. Maximum Candies You Can Get from Boxes 你能从盒子里获得的最大糖果数
You have n
boxes labeled from 0
to n - 1
. You are given four arrays: status
, candies
, keys
, and containedBoxes
where:
status[i]
is1
if theith
box is open and0
if theith
box is closed,candies[i]
is the number of candies in theith
box,keys[i]
is a list of the labels of the boxes you can open after opening theith
box.containedBoxes[i]
is a list of the boxes you found inside theith
box.
You are given an integer array initialBoxes
that contains the labels of the boxes you initially have. You can take all the candies in any open box and you can use the keys in it to open new boxes and you also can use the boxes you find in it.
Return the maximum number of candies you can get following the rules above.
Example 1:
Input: status = [1,0,1,0], candies = [7,5,4,100], keys = [[],[],[1],[]], containedBoxes = [[1,2],[3],[],[]], initialBoxes = [0] Output: 16 Explanation: You will be initially given box 0. You will find 7 candies in it and boxes 1 and 2. Box 1 is closed and you do not have a key for it so you will open box 2. You will find 4 candies and a key to box 1 in box 2. In box 1, you will find 5 candies and box 3 but you will not find a key to box 3 so box 3 will remain closed. Total number of candies collected = 7 + 4 + 5 = 16 candy.
Example 2:
Input: status = [1,0,0,0,0,0], candies = [1,1,1,1,1,1], keys = [[1,2,3,4,5],[],[],[],[],[]], containedBoxes = [[1,2,3,4,5],[],[],[],[],[]], initialBoxes = [0] Output: 6 Explanation: You have initially box 0. Opening it you can find boxes 1,2,3,4 and 5 and their keys. The total number of candies will be 6.
Constraints:
n == status.length == candies.length == keys.length == containedBoxes.length
1 <= n <= 1000
status[i]
is either0
or1
.1 <= candies[i] <= 1000
0 <= keys[i].length <= n
0 <= keys[i][j] < n
- All values of
keys[i]
are unique. 0 <= containedBoxes[i].length <= n
0 <= containedBoxes[i][j] < n
- All values of
containedBoxes[i]
are unique. - Each box is contained in one box at most.
0 <= initialBoxes.length <= n
0 <= initialBoxes[i] < n
这道题给了n个盒子,有的是锁着的,有的是打开的,由一个数组 status 来控制,其中 status[i] 表示盒子i的状态,1表示打开,0表示锁着。盒子里装着三种东西,糖果,钥匙,和其他盒子。数组 candies[i] 表示盒子i中的糖果个数,keys[i] 表示盒子i中的所有钥匙,containedBoxes[i] 表示盒子i中的其他所有盒子。起始的时候给了你一些盒子,问最多能获得多少糖果。这道题有点像个小游戏,打开宝箱得金币的那种,有的宝箱还需要钥匙开启。这里给的起始的盒子不一定都是打开,要去状态数组里面去查看,若为1,才能打开盒子,由于盒子里面有三种东西,糖果就直接加到结果 res 中,对于钥匙的处理可以直接更新状态数组 status,将对应的盒子状态改为1。对于盒子中的其他盒子,也要记录下来,以便之后继续打开。
这其实就是一种广度优先遍历 Breadth-first Search,每次都遍历完当前拥有的盒子,再去遍历得到的新的盒子。这里不用使用队列 queue,可以直接使用一个数组 boxes,初始化更新为 initialBoxes。循环的条件是 boxes 数组不为空,且当前有新的盒子被打开了(因为可能当前的盒子都是锁着的,没有新的盒子可以打开就会陷入死循环),所以这里用一个布尔型变量 changed 来记录是否有新的盒子被打开,初始化为 true。在循环中,先将 changed 赋值为 false,然后新建一个数组 newBoxes,遍历数组 boxes,对于每个遍历到的盒子 box,查看 status 数组,若盒子是打开的,则 changed 赋值为 true,且将该盒子里所有的其他盒子都加到 newBoxes 数组中,并且根据该盒子里的所有钥匙来更新状态数组 status,把盒子里的糖果均加到结果 res 中;若盒子是锁上的,直接把该盒子加到 newBoxes 中期待在下次遍历中可以打开。遍历完了 boxes 数组后,将其赋值为 newBoxes 进行下次遍历即可,参见代码如下:
class Solution { public: int maxCandies(vector<int>& status, vector<int>& candies, vector<vector<int>>& keys, vector<vector<int>>& containedBoxes, vector<int>& initialBoxes) { int res = 0; bool changed = true; vector<int> boxes = initialBoxes; while (!boxes.empty() && changed) { changed = false; vector<int> newBoxes; for (int box : boxes) { if (status[box]) { changed = true; newBoxes.insert(end(newBoxes), begin(containedBoxes[box]), end(containedBoxes[box])); for (int key : keys[box]) status[key] = 1; res += candies[box]; } else { newBoxes.push_back(box); } } swap(boxes, newBoxes); } return res; } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/1298
参考资料:
https://leetcode.com/problems/maximum-candies-you-can-get-from-boxes/
https://leetcode.com/problems/maximum-candies-you-can-get-from-boxes/discuss/458430/C%2B%2B-Queue
https://leetcode.com/problems/maximum-candies-you-can-get-from-boxes/discuss/458430/C%2B%2B-Queue