Here's the Gurobi code to solve the optimization problem:

```python
from gurobipy import Model, GRB, quicksum

# Create a new model
m = Model("optimization_problem")

# Create variables
dale_hours = m.addVar(vtype=GRB.INTEGER, name="dale_hours")
hank_hours = m.addVar(vtype=GRB.CONTINUOUS, name="hank_hours")
george_hours = m.addVar(vtype=GRB.INTEGER, name="george_hours")
bobby_hours = m.addVar(vtype=GRB.INTEGER, name="bobby_hours")
laura_hours = m.addVar(vtype=GRB.INTEGER, name="laura_hours")

# Set objective function
m.setObjective(3.39*dale_hours**2 + 4.91*dale_hours*hank_hours + 6.53*dale_hours*george_hours + 7.29*dale_hours*bobby_hours + 8.13*dale_hours*laura_hours + 7.6*hank_hours**2 + 9.61*hank_hours*george_hours + 6.55*hank_hours*laura_hours + 9.68*george_hours**2 + 4.11*george_hours*bobby_hours + 9.08*george_hours*laura_hours + 9.4*laura_hours**2 + 2.71*dale_hours + 7.89*george_hours + 9.21*bobby_hours + 5.64*laura_hours, GRB.MINIMIZE)

# Add constraints
m.addConstr(bobby_hours + laura_hours >= 18)
m.addConstr(dale_hours**2 + george_hours**2 >= 14)
m.addConstr(6*hank_hours + laura_hours >= 23)
m.addConstr(6*hank_hours + bobby_hours >= 24)
m.addConstr(dale_hours + bobby_hours >= 18)
m.addConstr(dale_hours + hank_hours + george_hours + bobby_hours + laura_hours >= 18)
m.addConstr(12*dale_hours**2 + 10*hank_hours**2 >= 39)
m.addConstr(12*dale_hours + 2*george_hours >= 45)
m.addConstr(12*dale_hours + 12*bobby_hours >= 30)
m.addConstr(12*dale_hours**2 + 10*hank_hours**2 + 2*george_hours**2 >= 37)
m.addConstr(12*dale_hours + 10*hank_hours + 12*bobby_hours >= 37)
m.addConstr(10*hank_hours + 12*bobby_hours + 7*laura_hours >= 37)
m.addConstr(12*dale_hours**2 + 10*hank_hours**2 + 2*george_hours**2 >= 33)
m.addConstr(12*dale_hours + 10*hank_hours + 12*bobby_hours >= 33)
m.addConstr(10*hank_hours + 12*bobby_hours + 7*laura_hours >= 33)
m.addConstr(12*dale_hours + 10*hank_hours + 2*george_hours >= 41)
m.addConstr(12*dale_hours + 10*hank_hours + 12*bobby_hours >= 41)
m.addConstr(10*hank_hours + 12*bobby_hours + 7*laura_hours >= 41)
m.addConstr(12*dale_hours + 10*hank_hours + 2*george_hours + 12*bobby_hours + 7*laura_hours >= 41)
m.addConstr(4*dale_hours - 7*george_hours >= 0)
m.addConstr(-9*george_hours + 8*bobby_hours >= 0)
m.addConstr(bobby_hours + laura_hours <= 107)
m.addConstr(dale_hours**2 + 6*hank_hours**2 + 12*george_hours**2 <= 135)
m.addConstr(dale_hours**2 + 6*hank_hours**2 + laura_hours**2 <= 83)
m.addConstr(12*george_hours + bobby_hours + laura_hours <= 52)
m.addConstr(dale_hours + bobby_hours + laura_hours <= 129)
m.addConstr(dale_hours + 12*george_hours + bobby_hours <= 120)
m.addConstr(6*hank_hours + 12*george_hours + laura_hours <= 113)
m.addConstr(6*hank_hours + 12*george_hours + bobby_hours <= 129)
m.addConstr(dale_hours + 12*george_hours + laura_hours <= 78)
m.addConstr(6*hank_hours + bobby_hours + laura_hours <= 94)
m.addConstr(12*dale_hours**2 + 10*hank_hours**2 + 7*laura_hours**2 <= 106)
m.addConstr(12*dale_hours + 10*hank_hours + 2*george_hours <= 189)
m.addConstr(12*dale_hours + 2*george_hours + 12*bobby_hours <= 93)
m.addConstr(10*hank_hours**2 + 2*george_hours**2 + 12*bobby_hours**2 <= 148)
m.addConstr(10*hank_hours + 12*bobby_hours + 7*laura_hours <= 234)
m.addConstr(12*dale_hours**2 + 2*george_hours**2 + 7*laura_hours**2 <= 202)
m.addConstr(2*george_hours + 12*bobby_hours + 7*laura_hours <= 135)


# Optimize model
m.optimize()

# Print results
if m.status == GRB.OPTIMAL:
    print('Obj: %g' % m.objVal)
    print('Dale Hours:', dale_hours.x)
    print('Hank Hours:', hank_hours.x)
    print('George Hours:', george_hours.x)
    print('Bobby Hours:', bobby_hours.x)
    print('Laura Hours:', laura_hours.x)
elif m.status == GRB.INFEASIBLE:
    print('The model is infeasible.')
else:
    print('Optimization ended with status %d' % m.status)
```