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

```python
import gurobipy as gp

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

# Create variables
hank_hours = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="hank_hours")
ringo_hours = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="ringo_hours")
dale_hours = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="dale_hours")
bobby_hours = m.addVar(lb=0, vtype=gp.GRB.INTEGER, name="bobby_hours")

# Set objective function
m.setObjective(3.19 * hank_hours + 1.64 * ringo_hours + 2.01 * dale_hours + 2.72 * bobby_hours, gp.GRB.MINIMIZE)

# Add constraints
m.addConstr(2 * hank_hours + 15 * ringo_hours >= 26)
m.addConstr(15 * ringo_hours + 1 * dale_hours >= 30)
m.addConstr(2 * hank_hours + 1 * dale_hours >= 10)
m.addConstr(2 * hank_hours + 16 * bobby_hours >= 21)
m.addConstr(2 * hank_hours + 15 * ringo_hours + 1 * dale_hours >= 18)
m.addConstr(2 * hank_hours + 15 * ringo_hours + 16 * bobby_hours >= 18)
m.addConstr(2 * hank_hours + 15 * ringo_hours + 1 * dale_hours >= 22)
m.addConstr(2 * hank_hours + 15 * ringo_hours + 16 * bobby_hours >= 22)
m.addConstr(2 * hank_hours + 15 * ringo_hours + 1 * dale_hours + 16 * bobby_hours >= 22)
m.addConstr(4 * ringo_hours + 15 * dale_hours >= 43)
m.addConstr(14 * hank_hours + 15 * bobby_hours >= 36)
m.addConstr(15 * dale_hours + 15 * bobby_hours >= 23)
m.addConstr(14 * hank_hours + 4 * ringo_hours + 15 * dale_hours + 15 * bobby_hours >= 23)
m.addConstr(7 * dale_hours + 11 * bobby_hours >= 47)
m.addConstr(10 * hank_hours + 7 * dale_hours >= 27)
m.addConstr(3 * ringo_hours + 11 * bobby_hours >= 29)
m.addConstr(10 * hank_hours + 3 * ringo_hours >= 29)
m.addConstr(10 * hank_hours + 11 * bobby_hours >= 76)
m.addConstr(10 * hank_hours + 7 * dale_hours + 11 * bobby_hours >= 65)
m.addConstr(3 * ringo_hours + 7 * dale_hours + 11 * bobby_hours >= 65)
m.addConstr(10 * hank_hours + 3 * ringo_hours + 7 * dale_hours >= 65)
m.addConstr(10 * hank_hours + 7 * dale_hours + 11 * bobby_hours >= 41)
m.addConstr(3 * ringo_hours + 7 * dale_hours + 11 * bobby_hours >= 41)
m.addConstr(10 * hank_hours + 3 * ringo_hours + 7 * dale_hours >= 41)
m.addConstr(10 * hank_hours + 7 * dale_hours + 11 * bobby_hours >= 73)
m.addConstr(3 * ringo_hours + 7 * dale_hours + 11 * bobby_hours >= 73)
m.addConstr(10 * hank_hours + 3 * ringo_hours + 7 * dale_hours >= 73)
m.addConstr(10 * hank_hours + 3 * ringo_hours + 7 * dale_hours + 11 * bobby_hours >= 73)
m.addConstr(4 * dale_hours - 3 * bobby_hours >= 0)
m.addConstr(7 * hank_hours - 10 * dale_hours >= 0)
m.addConstr(15 * ringo_hours + 1 * dale_hours <= 83)
m.addConstr(2 * hank_hours + 1 * dale_hours <= 89)
m.addConstr(2 * hank_hours + 15 * ringo_hours <= 89)
m.addConstr(2 * hank_hours + 15 * ringo_hours + 1 * dale_hours <= 49)
m.addConstr(4 * ringo_hours + 15 * dale_hours <= 143)
m.addConstr(14 * hank_hours + 15 * bobby_hours <= 126)
m.addConstr(14 * hank_hours + 15 * dale_hours <= 104)
m.addConstr(4 * ringo_hours + 15 * bobby_hours <= 101)
m.addConstr(10 * hank_hours + 7 * dale_hours <= 316)
m.addConstr(10 * hank_hours + 3 * ringo_hours + 11 * bobby_hours <= 218)
m.addConstr(3 * ringo_hours + 7 * dale_hours + 11 * bobby_hours <= 219)


# Optimize model
m.optimize()

# Print results
if m.status == gp.GRB.OPTIMAL:
    print('Optimal objective: %g' % m.objVal)
    for v in m.getVars():
        print('%s %g' % (v.varName, v.x))
elif m.status == gp.GRB.INFEASIBLE:
    print('Model is infeasible')
else:
    print('Optimization ended with status %d' % m.status)
```
