Maximum Profit of Operating a Centennial Wheel: Simulation
You are operating a centennial wheel with four gondolas, each holding up to maxCapacity passengers. Customers arrive in batches given by the array customers[i]. On each rotation, you board as many waiting customers as possible (up to the gondola capacity), earn boardingCost per passenger boarded, and pay runningCost for the rotation. Find the minimum number of rotations to maximize profit. If no positive profit is possible, return -1.
This is LeetCode 1599: Maximum Profit of Operating a Centennial Wheel, a medium problem that tests your ability to simulate a process step by step while tracking an optimal stopping point. The key is to avoid overcomplicating it. You do not need dynamic programming or greedy tricks. You just need to simulate each rotation faithfully.
Why this problem matters
This problem is a clean example of the simulation pattern. Many real-world optimization problems work the same way: process events in order, maintain running state, and track the best outcome you have seen so far. The simulation pattern appears in scheduling problems, resource management, and any scenario where you process a stream of inputs while tracking a cumulative metric.
It also tests precision with the details. You need to handle the queue correctly, cap boarding at the gondola capacity, continue rotations after all arrivals are processed if customers are still waiting, and compare running profit against a stored best. Getting all of these right in one pass is what makes this problem a useful exercise.
The key insight
There is no shortcut here. You cannot determine the optimal stopping point without simulating each rotation. The reason is that profit changes non-monotonically: it can rise, plateau, or fall depending on the flow of arriving customers. The maximum might occur at any rotation, including one after the last batch of arrivals.
The approach is:
- Simulate each rotation one at a time.
- Maintain a
waitingcounter for customers who have not yet boarded. - On each rotation, board
min(waiting, maxCapacity)customers. Add to total revenue, add the running cost. - Compute current profit (total revenue minus total cost). If it exceeds the best profit seen so far, record this rotation number.
- Continue until all arrivals have been processed and no one is left waiting.
- Return the rotation with the best profit, or
-1if the best profit was never positive.
The solution
def min_operations_max_profit(customers, boarding_cost, running_cost):
waiting = 0
total_boarded = 0
total_cost = 0
best_profit = 0
best_rotation = -1
rotation = 0
i = 0
while i < len(customers) or waiting > 0:
if i < len(customers):
waiting += customers[i]
i += 1
rotation += 1
board = min(waiting, 4)
waiting -= board
total_boarded += board
revenue = total_boarded * boarding_cost
total_cost += running_cost
profit = revenue - total_cost
if profit > best_profit:
best_profit = profit
best_rotation = rotation
return best_rotation
Here is what each piece does:
waitingtracks how many customers are in the queue and have not boarded yet. Each rotation, new arrivals (if any) are added, then up to 4 board.total_boardedaccumulates all passengers who have ever boarded. Revenue is alwaystotal_boarded * boarding_cost.total_costgrows byrunning_coston every rotation, regardless of how many passengers board.profitis computed fresh each rotation asrevenue - total_cost. This avoids floating-point issues or incremental drift.- The loop continues past the end of the
customersarray if people are still waiting. This is critical because the maximum profit rotation often comes after the last batch of arrivals. best_rotationis updated wheneverprofitstrictly exceedsbest_profit. If profit never goes positive,best_rotationstays at-1.
The loop condition i < len(customers) or waiting > 0 is the most important detail. If you only loop through the arrivals array, you will miss rotations where leftover waiting customers board and push profit higher.
Visual walkthrough
Let's trace through the example customers = [8, 3, 5, 5, 2] with boardingCost = 6, runningCost = 4, and maxCapacity = 4.
Rotation 1: 8 customers arrive
8 arrive, board 4 (max capacity). 4 remain waiting. Revenue = 4 * 6 = 24. Cost = 4. Profit = 20.
Rotation 2: 3 customers arrive
3 arrive, queue is now 7. Board 4. 3 still waiting. Revenue = 48, cost = 8. Profit = 40.
Rotation 3: 5 customers arrive
5 arrive, queue is now 8. Board 4. 4 still waiting. Revenue = 72, cost = 12. Profit = 60.
Rotation 4: 5 customers arrive
5 arrive, queue is now 9. Board 4. 5 still waiting. Revenue = 96, cost = 16. Profit = 80.
Rotation 5: 2 customers arrive
2 arrive, queue is now 7. Board 4. 3 still waiting. Revenue = 120, cost = 20. Profit = 100.
Rotation 6: no new arrivals(MAX PROFIT)
No new arrivals. Board remaining 3. Revenue = 138, cost = 24. Profit = 114. This is the maximum.
Rotation 7: no customers left
No one to board. Revenue stays at 138, cost rises to 28. Profit drops to 110. Continuing further only loses money.
The profit peaks at rotation 6 with a profit of 114. After that, continuing to rotate with no new passengers only adds cost. The answer is 6.
Complexity analysis
| Metric | Value |
|---|---|
| Time | O(n + w/4) where n = len(customers), w = total waiting overflow |
| Space | O(1), only a few integer variables |
The loop runs once per rotation. Each rotation boards up to 4 customers, so the total number of rotations is at most n + (total_customers) / 4. In the worst case, this is proportional to the sum of the customers array. Space is constant since you only track a handful of counters.
The building blocks
This problem relies on two reusable patterns that CodeBricks drills independently.
1. Simulation with running state
The pattern of processing events in sequence while maintaining counters:
state = initial_values
for event in events:
update(state, event)
if state meets condition:
record(state)
In this problem, the "events" are the customer arrivals (plus extra rotations for remaining passengers). The state includes waiting, total_boarded, and total_cost. The condition check is whether profit exceeds the recorded best. This same skeleton applies to problems like task scheduling, stock trading with cooldowns, and queue simulation problems.
2. Track-the-best pattern
The pattern of scanning through a sequence and remembering the position of the best result:
best_value = initial
best_index = -1
for i, value in enumerate(sequence):
if value > best_value:
best_value = value
best_index = i
return best_index
This shows up in problems like Best Time to Buy and Sell Stock (track min price, max profit), Gas Station (track the best starting index), and any problem where you need the index of an optimal value rather than the value itself.
Edge cases
Before submitting, make sure your solution handles these:
- Running cost exceeds revenue per full gondola: if
4 * boardingCost<=runningCost, then even a fully loaded rotation does not turn a profit. In this case, the answer is-1unless earlier rotations with accumulated passengers happen to create a positive profit. - Single customer batch
customers = [10]: 10 customers arrive at once. You need 3 rotations (4 + 4 + 2) to board them all. The profit calculation must continue past the array. - Zero customers in some rounds
customers = [0, 0, 0, 5]: the first three rotations are pure cost. Profit goes negative before eventually recovering. The answer depends on whether the recovery exceeds the early losses. - All customers fit in one rotation
customers = [3]withmaxCapacity = 4: only one rotation needed. Profit =3 * boardingCost - runningCost. If this is positive, return 1. Otherwise, return -1.
From understanding to recall
You have read through the simulation and it makes sense. Track waiting customers, board up to capacity each rotation, compute profit, remember the best. Clean and methodical. But can you reproduce it from scratch under time pressure?
The details matter: continuing the loop while waiting > 0 even after all arrivals, using min(waiting, 4) for boarding, computing profit as total_boarded * boardingCost - total_cost rather than incrementally. These are easy to get wrong when you are writing fast.
Spaced repetition fixes this. You write the simulation loop from memory at increasing intervals. After a few rounds, the pattern is automatic. You see "simulate a process, track the best state" and the structure flows out without hesitation.
The simulation pattern is one of roughly 60 reusable building blocks that cover hundreds of LeetCode problems. Learning them individually and drilling them with spaced repetition is far more effective than grinding random problems and hoping the patterns stick.
Related posts
- Gas Station - Another problem involving circular processing with running state and an optimal starting point
- Best Time to Buy and Sell Stock - Uses the same "track the best value seen so far" pattern in a single pass
- Queue Reconstruction by Height - A greedy simulation where processing order determines the final result
CodeBricks breaks the centennial wheel problem into its simulation and track-the-best building blocks, then drills them independently with spaced repetition. You type each piece from scratch until the pattern is automatic. When a simulation question shows up in your interview, you do not think about it. You just write it.