写在前面
特别感谢坑神的讲解 www.bilibili.com/video/BV1Ti…
这篇题解的代码基本照抄坑神的代码@wnjxyk
原文地址:leetcode-cn.com/problems/ma…
题目描述
有一个甜甜圈商店,每批次都烤 batchSize 个甜甜圈。这个店铺有个规则,就是在烤一批新的甜甜圈时,之前 所有 甜甜圈都必须已经全部销售完毕。给你一个整数 batchSize 和一个整数数组 groups ,数组中的每个整数都代表一批前来购买甜甜圈的顾客,其中 groups[i] 表示这一批顾客的人数。每一位顾客都恰好只要一个甜甜圈。
当有一批顾客来到商店时,他们所有人都必须在下一批顾客来之前购买完甜甜圈。如果一批顾客中第一位顾客得到的甜甜圈不是上一组剩下的,那么这一组人都会很开心。
你可以随意安排每批顾客到来的顺序。请你返回在此前提下,最多 有多少组人会感到开心。
示例 1:
输入:batchSize = 3, groups = [1,2,3,4,5,6]
输出:4
解释:你可以将这些批次的顾客顺序安排为 [6,2,4,5,1,3] 。那么第 1,2,4,6 组都会感到开心。
示例 2:
输入:batchSize = 4, groups = [1,3,2,5,2,2,1,6]
输出:4
提示:
1 <= batchSize <= 9
1 <= groups.length <= 30
1 <= groups[i] <= 109
解题思路
答题关键:
- 所有数据都应该在 %BatchSize 的环境下进行运算
- dp数组:
dp[mod][(count_1, ... , count_bs-1)]
:表示这种情况下的最多高兴组数mod
:表示前面安排过的组中总人数 mod BatchSize
的个数(count_1, ... , count_bs-1)
:表示当前未安排的每组的人数
- 转移方程:
mod:mod = (mod+x) % BatchSize
count_x:count_x -= 1
(两式的x为同一个x)
- 实际dp数组为:
unordered_map<LL, int> dp
,其中long long
数据中存储的是mod+[count]
的state,int
数据中存储的是最多高兴组数。具体地说,mod
存储在cur[0]
中,count_i
存储在cur[i]
中
代码
class Solution {
public:
using LL = long long;
// dp[mod][count_1, ... , count_i]
// mod: 前面安排过的组人数模BS等于mod
// count_1, ... , count_i: 当前未安排的组的人数
// 转移方程:mod = (mod+x) % BS, count_x -= 1
unordered_map<LL, int> dp;
vector<int> cur;
int BS; // batchSize
LL vec_to_ll() {
LL ret = 0;
for(int i = 0; i < BS; i++)
ret = ret * 32LL + cur[i];
return ret;
}
void ll_to_vec(LL ret) {
for(int i = BS-1; i >= 0; i--) {
cur[i] = ret % 32;
ret /= 32;
}
}
int dfs(LL state) {
// 当前state已计算过,直接返回
if(dp.count(state))
return dp[state];
int ret = 0;
bool flag = false;
// 注意这里,要从1开始
// 因为cur[0] 存储的是mod信息
for(int i = 1; i < BS; i++) {
// 将 ll 映射到 vec 上
// 这里存在一些重复计算的问题,但问题不大
ll_to_vec(state);
// 该位无元素,继续看下一位
if(cur[i] == 0)
continue;
// 进行操作,改变flag
flag = true;
// 将第i位的放到第0位
cur[0] = (cur[0] + i) % BS;
cur[i] -= 1;
// 递归
ret = max(ret, dfs(vec_to_ll()));
}
// 回溯,重置vec
ll_to_vec(state);
if(cur[0] == 0 && flag)
ret += 1;
dp[state] = ret;
return ret;
}
int maxHappyGroups(int batchSize, vector<int>& groups) {
int n = groups.size();
BS = batchSize;
cur.resize(BS, 0);
for(int i = 0; i < n; i++)
cur[groups[i] % BS]++;
int ans = cur[0];
cur[0] = 0;
return dfs(vec_to_ll()) + ans;
}
};