UVa 10026 - Shoemaker's Problem

Summary
A problem with a very easy greedy sorting implementation, but whose proof of correctness requires a bit of thinking.

Explanation
We are to help an overburdened shoemaker who must pay a fee for everyday that he has not finished a job. He has N <= 1000 jobs, the ith job takes a time $$T_i$$ to complete and has daily unfinished cost of $$S_i$$. We must help the shoemaker minimize the amount of fines that he must pay by finding the optimal order in which to make the shoes. In the case of ties, we should output the lexicographically smallest permutation corresponding to the order of the jobs.

First observe that we can find the minimum cost using only pairwise comparisions of the jobs; we don't need to check every possible permutation. Consider the decision of placing task i before or after task j, which are the two best options to consider for the next task. If we place i directly before j, or j directly before i, the total cost paid for not finishing the other N - 2 tasks does not depend on our choice of the order between i and j.

To decide whether to pick i over j, we simply pick the task with the largest fine per day/days to complete ratio. Let item i have cost per day a and take b days to complete, and let item j have cost per day c and take d days to complete. Assume $$a/b > c/d$$, so i has the greater cost per day ratio. Then $$ad > cb$$

$$ad + ab + cd > cb + ab + cd$$

$$a(b + d) + cd > c(b + d) + ab$$

But now $$a(b + d) + cd$$ is the cost of doing task j first, since we pay cost c for d days of not completing job j, and cost a for b + d days of not completing job i. Likewise, $$c(b + d) + ab$$ is the cost of doing task i first. Thus, the cost of doing job j (the job with the lesser ratio) first is greater, and thus should be avoided.

Implementation
Use the STL Stable Sort for a quick C++ implementation.

Input
4

4 3 4 1 1000 2 2 5 5

3 1 1 2 2 3 3

5 3 2 3 5 9999 9998 2 3 10000 10000

3 123 123 3 3 5 5

Output
2 1 3 4

1 2 3

2 4 5 3 1

1 2 3