Approximation algorithms and the hardness of approximation