```python
import gurobipy as gp
from gurobipy import GRB

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

# Create variables
bill_hours = m.addVar(lb=0, vtype=GRB.CONTINUOUS, name="Bill_hours")
peggy_hours = m.addVar(lb=0, vtype=GRB.CONTINUOUS, name="Peggy_hours")
hank_hours = m.addVar(lb=0, vtype=GRB.CONTINUOUS, name="Hank_hours")

# Set objective function
m.setObjective(bill_hours**2 + 9*bill_hours*peggy_hours + 8*peggy_hours**2 + peggy_hours*hank_hours + 7*peggy_hours + 7*hank_hours, GRB.MINIMIZE)

# Add constraints
m.addConstr(0.46 * bill_hours**2 + 10.12 * hank_hours**2 >= 39, "c1")
m.addConstr(6.72 * peggy_hours + 10.12 * hank_hours >= 18, "c2")
m.addConstr(0.46 * bill_hours + 6.72 * peggy_hours + 10.12 * hank_hours >= 18, "c3")
m.addConstr(1.82 * bill_hours + 2.03 * peggy_hours >= 16, "c4")
m.addConstr(2.03 * peggy_hours + 5.95 * hank_hours >= 36, "c5")
m.addConstr(1.82 * bill_hours + 2.03 * peggy_hours + 5.95 * hank_hours >= 34, "c6")
m.addConstr(6.95 * bill_hours + 12.71 * hank_hours >= 31, "c7")
m.addConstr(6.95 * bill_hours + 1.29 * peggy_hours >= 47, "c8")
m.addConstr(6.95 * bill_hours + 1.29 * peggy_hours + 12.71 * hank_hours >= 47, "c9")
m.addConstr(8.81 * bill_hours**2 + 9.2 * hank_hours**2 >= 11, "c10")
m.addConstr(8.81 * bill_hours + 1.9 * peggy_hours >= 14, "c11")
m.addConstr(8.81 * bill_hours + 1.9 * peggy_hours + 9.2 * hank_hours >= 14, "c12")
m.addConstr(4.17 * bill_hours + 10.11 * peggy_hours >= 31, "c13")
m.addConstr(10.11 * peggy_hours**2 + 0.97 * hank_hours**2 >= 30, "c14")
m.addConstr(4.17 * bill_hours + 10.11 * peggy_hours + 0.97 * hank_hours >= 30, "c15")
m.addConstr(5 * peggy_hours - 5 * hank_hours >= 0, "c16")
m.addConstr(2.03 * peggy_hours + 5.95 * hank_hours <= 88, "c17")
m.addConstr(1.82 * bill_hours**2 + 2.03 * peggy_hours**2 <= 54, "c18")
m.addConstr(4.17 * bill_hours + 10.11 * peggy_hours <= 62, "c19")
m.addConstr(4.17 * bill_hours**2 + 10.11 * peggy_hours**2 + 0.97 * hank_hours**2 <= 96, "c20")


# Optimize model
m.optimize()

# Print results
if m.status == GRB.OPTIMAL:
    print('Obj: %g' % m.objVal)
    print('Bill Hours: %g' % bill_hours.x)
    print('Peggy Hours: %g' % peggy_hours.x)
    print('Hank Hours: %g' % hank_hours.x)
elif m.status == GRB.INFEASIBLE:
    print('Model is infeasible')
else:
    print('Optimization ended with status %d' % m.status)
```