[难题折磨王] LC5707. 得到新鲜甜甜圈的最多组数

606 阅读2分钟

写在前面

特别感谢坑神的讲解 www.bilibili.com/video/BV1Ti…

这篇题解的代码基本照抄坑神的代码@wnjxyk

原文地址:leetcode-cn.com/problems/ma…

题目描述

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

解题思路

答题关键:

  1. 所有数据都应该在 %BatchSize 的环境下进行运算
  2. dp数组:
  • dp[mod][(count_1, ... , count_bs-1)]:表示这种情况下的最多高兴组数
  • mod:表示前面安排过的组中总人数 mod BatchSize 的个数
  • (count_1, ... , count_bs-1):表示当前未安排的每组的人数
  1. 转移方程:
  • mod:mod = (mod+x) % BatchSize
  • count_x:count_x -= 1 (两式的x为同一个x)
  1. 实际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;
    }
};