Description

你正在经营一座摩天轮,该摩天轮共有 4 个座舱 ,每个座舱 最多可以容纳 4 位游客 。你可以 逆时针 轮转座舱,但每次轮转都需要支付一定的运行成本 runningCost 。摩天轮每次轮转都恰好转动 1 / 4 周。

给你一个长度为 n 的数组 customers , customers[i] 是在第 i 次轮转(下标从 0 开始)之前到达的新游客的数量。这也意味着你必须在新游客到来前轮转 i 次。每位游客在登上离地面最近的座舱前都会支付登舱成本 boardingCost ,一旦该座舱再次抵达地面,他们就会离开座舱结束游玩。

你可以随时停下摩天轮,即便是 在服务所有游客之前 。如果你决定停止运营摩天轮,为了保证所有游客安全着陆,将免费进行所有后续轮转 。注意,如果有超过 4 位游客在等摩天轮,那么只有 4 位游客可以登上摩天轮,其余的需要等待 下一次轮转 。

返回最大化利润所需执行的 最小轮转次数 。 如果不存在利润为正的方案,则返回 -1 。

Constraints

  • \(1 \le n \le 10^5\)
  • \(0 \le customers_i \le 50\)
  • \(1 \le boardingCost, runningCost \le 100\)

Solution

题面很复杂(这次不化简描述了),但做法很简单。

有4位客人就塞进去,不足的话只能勉强上。每一轮的贡献都比较一下谁最优即可。

解法不是最优解,胜在简单。时间复杂度\({O(\frac{50}{4}n)}\)。

改成最优解了,\(O(n)\)。

Code

class Solution {
public:
    int minOperationsMaxProfit(vector<int>& customers, int boardingCost, int runningCost) {
        // sum of available customers
        int sum = 0;
        int profit = 0;
        int cur = 0;

        // {profit, rev-times}
        tuple<int, int> best {0, 1};

        auto fetch = [&](int batch = 1) {
            int board = min(4 * batch, sum);
            sum -= board;
            profit += board * boardingCost - batch * runningCost;
            cur += batch;

            auto cmp = make_tuple(profit, -cur);
            if(cmp > best) best = cmp;
        };

        for(auto &c : customers) {
            sum += c;
            fetch();
        }

        if(sum) {
            // %4 == 0
            // batch==0 has no effect
            int batch = sum / 4;
            fetch(batch);

            // fallthrough
            // %4 != 0
            fetch();
        }

        auto [_, rt] = best;
        return -rt;
    }
};

LeetCode-1599 Maximum Profit of Operating a Centennial Wheel