## Problem Description and Symbolic Representation

The problem can be broken down into the following symbolic representation:

### Variables
- $x_1$ : Number of ads in grocery stores
- $x_2$ : Number of ads at train stations
- $x_3$ : Number of ads in water parks

### Objective Function
Maximize the total viewership: $10000x_1 + 20000x_2 + 50000x_3$

### Constraints
1. Budget constraint: $300x_1 + 500x_2 + 1000x_3 \leq 50000$
2. Train station ad limit: $x_2 \leq 15$
3. Water park ad limit: $x_3 \leq \frac{1}{3}(x_1 + x_2 + x_3)$
4. Grocery store ad minimum: $x_1 \geq 0.1(x_1 + x_2 + x_3)$
5. Non-negativity constraints: $x_1, x_2, x_3 \geq 0$ and are integers.

## Symbolic Representation in JSON Format
```json
{
    'sym_variables': [('x1', 'ads in grocery stores'), ('x2', 'ads at train stations'), ('x3', 'ads in water parks')],
    'objective_function': '10000*x1 + 20000*x2 + 50000*x3',
    'constraints': [
        '300*x1 + 500*x2 + 1000*x3 <= 50000',
        'x2 <= 15',
        'x3 <= (1/3)*(x1 + x2 + x3)',
        'x1 >= 0.1*(x1 + x2 + x3)',
        'x1, x2, x3 >= 0'
    ]
}
```

## Gurobi Code in Python
```python
import gurobi

def solve_ads_problem():
    # Create a new model
    model = gurobi.Model()

    # Define variables
    x1 = model.addVar(name="x1", vtype=gurobi.GRB.INTEGER)  # ads in grocery stores
    x2 = model.addVar(name="x2", vtype=gurobi.GRB.INTEGER)  # ads at train stations
    x3 = model.addVar(name="x3", vtype=gurobi.GRB.INTEGER)  # ads in water parks

    # Objective function: Maximize viewership
    model.setObjective(10000*x1 + 20000*x2 + 50000*x3, gurobi.GRB.MAXIMIZE)

    # Budget constraint
    model.addConstr(300*x1 + 500*x2 + 1000*x3 <= 50000)

    # Train station ad limit
    model.addConstr(x2 <= 15)

    # Water park ad limit
    model.addConstr(x3 <= (1/3)*(x1 + x2 + x3))

    # Grocery store ad minimum
    model.addConstr(x1 >= 0.1*(x1 + x2 + x3))

    # Non-negativity constraints (implied by integer type)

    # Solve the model
    model.optimize()

    # Print solution
    if model.status == gurobi.GRB.OPTIMAL:
        print("Optimal solution found.")
        print(f"Ads in grocery stores: {x1.varValue}")
        print(f"Ads at train stations: {x2.varValue}")
        print(f"Ads in water parks: {x3.varValue}")
        print(f"Max viewership: {model.objVal}")
    else:
        print("No optimal solution found.")

solve_ads_problem()
```