# Champagne Tower
**Difficulty:** MEDIUM
[External](https://leetcode.com/problems/champagne-tower)
Canonical: https://scaleengineer.com/dsa/problems/champagne-tower
**Patterns:** [Dynamic Programming](https://scaleengineer.com/dsa/patterns/dynamic-programming)
**Companies:** [National Instruments](https://scaleengineer.com/companies/national-instruments)
---
## Problem
We stack glasses in a pyramid, where the **first** row has `1` glass, the **second** row has `2` glasses, and so on until the 100th row. Each glass holds one cup of champagne.

Then, some champagne is poured into the first glass at the top. When the topmost glass is full, any excess liquid poured will fall equally to the glass immediately to the left and right of it. When those glasses become full, any excess champagne will fall equally to the left and right of those glasses, and so on. (A glass at the bottom row has its excess champagne fall on the floor.)

For example, after one cup of champagne is poured, the top most glass is full. After two cups of champagne are poured, the two glasses on the second row are half full. After three cups of champagne are poured, those two cups become full - there are 3 full glasses total now. After four cups of champagne are poured, the third row has the middle glass half full, and the two outside glasses are a quarter full, as pictured below.

![](https://assets.glich.co/dsa/champagne-tower/image0.png)

Now after pouring some non-negative integer cups of champagne, return how full the `jth` glass in the `ith` row is (both `i` and `j` are 0-indexed.)

**Example 1:**

**Input:** poured = 1, query_row = 1, query_glass = 1
**Output:** 0.00000
**Explanation:** We poured 1 cup of champange to the top glass of the tower (which is indexed as (0, 0)). There will be no excess liquid so all the glasses under the top glass will remain empty.

**Example 2:**

**Input:** poured = 2, query_row = 1, query_glass = 1
**Output:** 0.50000
**Explanation:** We poured 2 cups of champange to the top glass of the tower (which is indexed as (0, 0)). There is one cup of excess liquid. The glass indexed as (1, 0) and the glass indexed as (1, 1) will share the excess liquid equally, and each will get half cup of champange.

**Example 3:**

**Input:** poured = 100000009, query_row = 33, query_glass = 17
**Output:** 1.00000

**Constraints:**

* `0 <= poured <= 109`
* `0 <= query_glass <= query_row < 100`

# Approaches
## Simulation with 2D Array
This approach simulates the flow of champagne through the pyramid of glasses row by row. We use a 2D array to store the amount of champagne that flows into each glass, which directly models the structure of the pyramid.
**Time:** O(R^2), where R is `query_row`. We have two nested loops, each running up to R times. · **Space:** O(R^2), where R is `query_row`. We use a 2D array of size approximately `(R+1) x (R+1)`.
**Pros:** Simple to understand and implement as it directly models the physical process.; Sufficiently efficient for the given constraints.
**Cons:** Uses more memory than necessary. The space complexity is quadratic with respect to the query row, which can be optimized.
### Explanation
We can model the pyramid as a 2D array, let's call it `tower`, where `tower[i][j]` represents the total amount of champagne that flows into the glass at row `i`, column `j`.
The size of this array needs to be at least `(query_row + 1) x (query_row + 1)`. A `102x102` array is sufficient given the constraints.
We start by pouring all the champagne, `poured`, into the top glass `tower[0][0]`.
Then, we iterate from the top row (`r = 0`) down to the `query_row`. For each glass `(r, c)` in the current row, we check if it has more champagne than its capacity (which is 1 cup).
If `tower[r][c] > 1`, the excess champagne `(tower[r][c] - 1)` is split equally and flows down to the two glasses below it: `(r+1, c)` and `(r+1, c+1)`. We update their values in the `tower` array accordingly by adding `excess / 2.0` to each.
After iterating through all necessary rows, the value `tower[query_row][query_glass]` will hold the total amount of champagne that has flowed into the target glass.
The amount of champagne actually held by the glass is this value, capped at 1.0. So, the final answer is `min(1.0, tower[query_row][query_glass])`.

```java
class Solution {
    public double champagneTower(int poured, int query_row, int query_glass) {
        double[][] tower = new double[102][102];
        tower[0][0] = (double) poured;

        for (int r = 0; r <= query_row; r++) {
            for (int c = 0; c <= r; c++) {
                if (tower[r][c] > 1.0) {
                    double excess = tower[r][c] - 1.0;
                    tower[r+1][c] += excess / 2.0;
                    tower[r+1][c+1] += excess / 2.0;
                }
            }
        }

        return Math.min(1.0, tower[query_row][query_glass]);
    }
}
```
### Algorithm
- Create a 2D array `tower` of `double`s with dimensions `(query_row + 2) x (query_row + 2)` to store the amount of champagne flowing into each glass. Initialize all elements to 0.
- Set the top glass `tower[0][0]` to the total amount `poured`.
- Iterate from row `r = 0` to `query_row`.
- Inside this loop, iterate through each glass `c` in the current row `r` (from `c = 0` to `r`).
- Check if the champagne in the current glass `tower[r][c]` exceeds its capacity of 1.0.
- If it does, calculate the `excess = tower[r][c] - 1.0`.
- Distribute this `excess` equally to the two glasses directly below it: `tower[r+1][c]` and `tower[r+1][c+1]` each receive `excess / 2.0`.
- After the loops complete, the value `tower[query_row][query_glass]` holds the total champagne that has flowed into the target glass.
- The final answer is the amount in the glass, which cannot exceed 1.0. So, return `min(1.0, tower[query_row][query_glass])`.

## Space-Optimized Simulation with 1D Array
This approach is an optimization of the 2D array simulation. We observe that to calculate the champagne flow for any given row, we only need the information from the immediately preceding row. This allows us to reduce the space complexity from O(R^2) to O(R), where R is the `query_row`, by using a single 1D array.
**Time:** O(R^2), where R is `query_row`. The nested loops dominate the runtime. · **Space:** O(R), where R is `query_row`. We use a single 1D array of size `R+2`.
**Pros:** Highly efficient in terms of space, using only linear extra space.; Maintains the same optimal time complexity as the 2D approach.
**Cons:** The in-place update logic with the right-to-left loop can be slightly less intuitive to grasp compared to the 2D array version.
### Explanation
Instead of a 2D array, we use a single 1D array, `dp`, of size `query_row + 2` to represent the flow of champagne. `dp[j]` will store the total amount of champagne flowing into glass `j` of the current row being processed.
We initialize `dp[0]` with the total `poured` amount, as all champagne starts at the top glass.
We then iterate from row `i = 0` up to `query_row - 1`. In each iteration `i`, we calculate the champagne distribution for the next row, `i+1`, based on the overflows from row `i`.
To update the `dp` array in-place, we must iterate through the glasses of the current row `i` from right to left (from `j = i` down to `0`). This is crucial because the new flow for `dp[j]` depends on the old flows from `dp[j]` and `dp[j-1]`. A right-to-left traversal ensures we use the old `dp[j]` value to update `dp[j+1]` before `dp[j]` itself is updated.
For each glass `(i, j)`, we calculate the `excess` flow, which is `max(0, dp[j] - 1.0)`. This excess is split in half, with `excess / 2.0` going to the left child `(i+1, j)` and `excess / 2.0` going to the right child `(i+1, j+1)`.
In our 1D array, this translates to: we set `dp[j]` to `excess / 2.0` and add `excess / 2.0` to `dp[j+1]`. The right-to-left update correctly accumulates the flows from both parents for the next row.
After the loops complete, `dp[query_glass]` contains the total flow into the target glass `(query_row, query_glass)`.
The final answer is `min(1.0, dp[query_glass])`.

```java
class Solution {
    public double champagneTower(int poured, int query_row, int query_glass) {
        double[] dp = new double[query_row + 2];
        dp[0] = (double) poured;

        for (int i = 0; i < query_row; i++) {
            for (int j = i; j >= 0; j--) {
                double excess = Math.max(0.0, dp[j] - 1.0);
                dp[j+1] += excess / 2.0;
                dp[j] = excess / 2.0;
            }
        }

        return Math.min(1.0, dp[query_glass]);
    }
}
```
### Algorithm
- Create a 1D array `dp` of `double`s with size `query_row + 2`.
- Initialize `dp[0] = poured`, representing the initial state at the top glass.
- Iterate from row `i = 0` to `query_row - 1`. This loop processes row `i` to calculate the flows for the next row, `i+1`.
- Inside this loop, iterate through the glasses of row `i` from right to left (from `j = i` down to `0`).
- For each glass `j`, calculate the total excess flow: `excess = Math.max(0.0, dp[j] - 1.0)`.
- The flow to the right child `(i+1, j+1)` is `excess / 2.0`. Add this amount to `dp[j+1]`.
- The flow to the left child `(i+1, j)` is also `excess / 2.0`. Update `dp[j]` to become this value. The right-to-left traversal ensures this update doesn't interfere with the calculation for other glasses in the same row.
- After the loops complete, `dp` holds the flow values for the `query_row`.
- Return `min(1.0, dp[query_glass])`.

# Solutions
### Java

```java
class Solution {
public
  double champagneTower(int poured, int query_row, int query_glass) {
    double[][] f = new double[101][101];
    f[0][0] = poured;
    for (int i = 0; i <= query_row; ++i) {
      for (int j = 0; j <= i; ++j) {
        if (f[i][j] > 1) {
          double half = (f[i][j] - 1) / 2.0;
          f[i][j] = 1;
          f[i + 1][j] += half;
          f[i + 1][j + 1] += half;
        }
      }
    }
    return f[query_row][query_glass];
  }
}

```

### CPP

```cpp
class Solution {
public:
  double champagneTower(int poured, int query_row, int query_glass) {
    double f[101][101] = {0.0};
    f[0][0] = poured;
    for (int i = 0; i <= query_row; ++i) {
      for (int j = 0; j <= i; ++j) {
        if (f[i][j] > 1) {
          double half = (f[i][j] - 1) / 2.0;
          f[i][j] = 1;
          f[i + 1][j] += half;
          f[i + 1][j + 1] += half;
        }
      }
    }
    return f[query_row][query_glass];
  }
};

```

### Python

```python
class Solution:
    def champagneTower(self, poured: int, query_row: int, query_glass: int) -> float: f = [[0] * 101 for _ in range(101)] f[0][0] = poured for i in range(query_row + 1): for j in range(i + 1): if f[i][j] > 1: half = (f[i][j] - 1) / 2 f[i][j] = 1 f[i + 1][j] += half f[i + 1][j + 1] += half return f[query_row][query_glass]

```
