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

```python
import gurobipy as gp

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

# Create variables
bill_hours = m.addVar(lb=0, name="bill_hours")  # Bill's hours worked
bobby_hours = m.addVar(lb=0, name="bobby_hours") # Bobby's hours worked

# Set objective function
m.setObjective(4.11 * bill_hours + 4.49 * bobby_hours, gp.GRB.MINIMIZE)

# Add constraints
m.addConstr(4 * bill_hours + 9 * bobby_hours >= 38, "dollar_cost_min") # Total dollar cost minimum
m.addConstr(4 * bill_hours + 9 * bobby_hours <= 87, "dollar_cost_max") # Total dollar cost maximum
m.addConstr(1 * bill_hours + 3 * bobby_hours >= 46, "quit_index_min") # Total quit index minimum
m.addConstr(1 * bill_hours + 3 * bobby_hours <= 94, "quit_index_max") # Total quit index maximum
m.addConstr(-2 * bill_hours + 2 * bobby_hours >= 0, "bill_bobby_ratio") # Ratio constraint


# Optimize model
m.optimize()

# Check for infeasibility
if m.status == gp.GRB.INFEASIBLE:
    print("The model is infeasible.")
else:
    # Print optimal solution
    print("Optimal Solution:")
    print(f"Hours worked by Bill: {bill_hours.x}")
    print(f"Hours worked by Bobby: {bobby_hours.x}")
    print(f"Objective Value: {m.objVal}")

```
