To solve this optimization problem, we need to define variables and constraints that capture the given conditions. Let's denote:

- $x_n$ as the number of posters placed at the northside mall,
- $x_s$ as the number of posters placed at the southside mall,
- $x_c$ as the number of posters placed at the central mall.

The objective is to maximize viewership, which can be calculated as $20000x_n + 50000x_s + 40000x_c$.

Given constraints are:
1. The cost constraint: $500x_n + 1000x_s + 800x_c \leq 30000$,
2. The southside mall limit: $x_s \leq 5$,
3. The central mall proportion limit: $x_c \leq \frac{1}{3}(x_n + x_s + x_c)$, which simplifies to $2x_c \leq x_n + x_s$,
4. The northside mall proportion requirement: $x_n \geq 0.2(x_n + x_s + x_c)$, which simplifies to $0.8x_n \geq 0.2x_s + 0.2x_c$, or $4x_n \geq x_s + x_c$.

All variables are non-negative integers since they represent the number of posters.

Let's express this problem in Gurobi code:

```python
from gurobipy import *

# Create a model
m = Model("Movie_Poster_Optimization")

# Define variables
x_n = m.addVar(vtype=GRB.INTEGER, name="northside_posters")
x_s = m.addVar(vtype=GRB.INTEGER, name="southside_posters")
x_c = m.addVar(vtype=GRB.INTEGER, name="central_posters")

# Objective function: Maximize viewership
m.setObjective(20000*x_n + 50000*x_s + 40000*x_c, GRB.MAXIMIZE)

# Constraints
m.addConstr(500*x_n + 1000*x_s + 800*x_c <= 30000, name="budget_constraint")
m.addConstr(x_s <= 5, name="southside_limit")
m.addConstr(2*x_c <= x_n + x_s, name="central_proportion")
m.addConstr(4*x_n >= x_s + x_c, name="northside_proportion")

# Solve the model
m.optimize()

# Print solution
if m.status == GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f"Northside posters: {x_n.x}")
    print(f"Southside posters: {x_s.x}")
    print(f"Central posters: {x_c.x}")
else:
    print("No optimal solution found")
```