蛋糕工厂产能规划 | 豆包MarsCode AI刷题

77 阅读3分钟

题目描述

原题链接:蛋糕工厂产能规划

简单来说,就是初始有 m 个机器,w 个工人,每天可以生产 m × w 个蛋糕。生产的蛋糕又可以拿去购买额外的机器或雇佣工人,机器和工人的成本都是 p 个蛋糕。

现在要求,生产 n 个蛋糕最少要多少天。

算法描述

从贪心的角度,要达到最大产能,应该在生产的初期就持续增加机器和工人数。因此,机器和工人数在生产过程中应该是一个持续上后,后续保持不变的一个过程,这样才可能花费最少的天数生产 n 个蛋糕。

故可以得出如下的贪心求解过程:

  1. 先计算截至今天生产的蛋糕总数 sum 是否超过 n,若超过,贪心求解过程结束。
  2. sum 不超过 n,则将蛋糕尽可能多的购置机器或雇佣工人,增加 m × w 的值
  3. 假设从今天开始,不再继续增加机器数和工人数,即每天最多生产 m × w 个蛋糕,计算总共需要花费多少天,更新最少天数 res
  4. 下一天的计算继续从步骤 1 开始

接下来,我们讨论机器数和工人数如何增加。

由于每天可以生产的蛋糕数是机器数和工人数的乘积,按照不等式的特性,假定 m + w 固定,要让 m × w 尽可能的大,应该让 m 和 w 之间尽可能接近。因此,我们得出购买额外的机器或雇佣工人的基本规则:若 m 大了则增加 w,若 w 大了则增加 m,直至二者尽可能相等。

贪心完整代码

public class Main {
    public static int solution(int m, int w, int p, int n) {
        // Please write your code here
        int res = n / (m * w + 1) + 1;
        int days = res;
        int sum = 0;
        for(int i = 1; i <= days; i++) {
            sum += m * w;
            if (sum >= n) {
                res = Math.min(res, i);
                break;
            }
            while( sum >= p ) {
                if (m < w) {
                    m++;
                } else {
                    w++;
                }
                sum -= p;
            }
            res = Math.min(res, i + (n - sum) / (m * w + 1) + 1);
        }
        System.out.println(res);
        return res;
    }

    public static void main(String[] args) {
        //  You can add more test cases here
        System.out.println(solution(3, 1, 2, 12) == 3);
        System.out.println(solution(10, 5, 30, 500) == 8);
        System.out.println(solution(3, 5, 30, 320) == 14);
    }
}

另一种思路:二分 + 贪心

虽然纯贪心的思路已经可以通过本题,但还有一种思路就是二分 + 贪心。

如果 m 和 w 的数量始终不变,我们可以得出最大所需天数为 n / (m + w + 1) + 1

也就是说,我们最少生产天数一定在 [1, n / (m + w + 1) + 1] 这个区间内

知道了这个区间,我们就可以使用二分查找缩短搜索区间,判断能否在给定时间 days 内完成 n 个蛋糕的生产。而判断过程则是利用上述的贪心策略。不同的是,如果在判断过程,发现当前生产的蛋糕数 sum 加上剩余天数 days - day 每天生产 m × w 的蛋糕数超过了 n,判断就可以提前终止,缩短搜索区间,继续查找最少天数。

这种方法的好处很明显,可以减小我们一开始的搜索区间,但坏处也很明显,贪心过程存在重复计算(但其实可以用额外变量存储中间状态的计算结果)