Lab 8: Skiing
Sugarloaf Ski Resortw will let you ski for free all winter, in
exchange for helping their ski rental shop with an algorithm to assign
skis to skiers. You have a set of pairs of skis, and a set of skiers.
Each skier needs to get a pair of skis.
Ideally, each skier should obtain a pair of skis whose heigth
matches his or her own height exactly. Unfortunately, this is
generally not possible. We define the disparity between a skier and
her pairs of skis as the absolute value of the difference between the
height of the skier and the height of the skis.
The objective is to find an assignment of skis to skiers that
minimizes the sum of the disparities.
- First, let's assume that there are m skiers and n pairs of skis
(that is, same number of pairs of skis and skiers).
One day, while waiting for the lift, you make an interesting
discovery: if we have a short person and a tall person, it would
never be better to give to the shorter person a taller pair of skis
than were given to the taller person.
Prove that this is always true.
Hint: Let P1, P2 be the length of two skiers, and S1, S2 the lengths
of the skis. We assume P1 < P2 and S1 < S2. Prove that pairing P1
with S1 and P2 with S2 is better than pairing P1 with S2 and P2 with
S1.
Basically we'd like to show that |P1 - S1| + |P2 - S2| <= |P1 - S2| +
|P2 - S1|. To prove this consider all possible cases:
- P1 < S1 < P2 < S2:
- P1 < S1 < S2 < P2:
- P1 < P2 < S1 < S2:
- S1 < P1 < P2 < S2:
- S1 < P1 < S2 < P2:
- S1 < S2 < P1 < P2:
- Using this observation, describe a greedy algorithm to assign
the (pairs of) skis to skiers, and argue why this algorithm is
correct. What is the time complexity of your algorithm?
- Your next task is to design an efficient algorithm for the more
general case where there are m skiers and n pairs of skis and m < n
(i.e. more skis than skiers).
The greedy solution above does not work in this case (can you come
up with a simple example?), so you'll come up with a dynamic
programming solution.
Here is some notation that may help you.
- Sort the skiers and skis
by increasing height.
- Let h[i] denote the height of the i-th skier
in sorted order, and s[j] denote the height of the j-th pair of skis
in sorted order.
- Let OPT(i,j) be the optimal cost (disparity) for matching the
first i skiers with skis from the set 1, 2, ..., j.
- The
solution we seek is simply OPT(m, n).
Define OPT(i,j) recursively.
- Illustrate your algorithm by explicitly filling out the table
OPT(i,j) for the following sample data: ski heights {1, 2, 5, 7,
13, 21}. Skier heights {3,4, 7, 11, 18}.
Note: This requires a lot of patience but it makes you really
understand what's going on. You may consider skipping this part and
going to the programming part below.
The skis and skiers in practice
Write code, in a language of your choice, to implement part (3) of the
skis and skiers problem above.
You need to implement TWO functions for finding OPT(i,j):
- One that corresponds to solving the problem recursively without
dynamic programming. You could name it OPT-recursive(i,j)
- One that corresponds to the dynamic programming solution. You
could name it OPT-dynprogr(i,j).
- Each function should take i,j as parameters, and should return the
optimal cost of the assignment (not the actual assignment of skis to
skiers; as usual we claim that it can be added easily). In this
assignment the goal is to get an understanding of the running time
with and without dynamic programming.
- The arrays that hold the heights of the skis and the skiers can be
global variables.
- The number of skiers and skis, m and n, need to be read from
the command line using argv and argc (if you use
c/c++); use something similar if you use python, but the idea is that
the user does not need to edit your code and recompile to change n and m.
- Initialize the skis and skiers height arrays with random values
that are reasonable for skis and skiers heights (assume that heights
are integers, in inches, so come up with a reasonable range).
- We will run your program like this:
g++ marty.cpp -o marty
./marty 100 200
you entered m=100 n=200
running opt_dynprogr with m=100, n=200: total time = ...
running opt_recursive with m=100, n=200: total time =
- Test both functions on increasing values of m and n, until you
notice a significant difference in running time between the two
methods.
- Run your code on the heights in part (4) above, and include
this table in your report.
- Drive to Sugarloaf, take a picture of yourself in front of
the lift, and post it on piazza.
- Collaboration policy: This problem is individual, you cannot
have a partner. But you can discuss it with anyone in the class, as
long as you follow the honor code.
- What to turn in:
- The solution to the version of this problem where the number of skis and skiers is tha same, together with a proof of correctness.
- email me the .cpp file so that we can test
it.
- A hard-copy of your code
- A report including:
- The solution table for part (4) above, that is, for
ski heights {1, 2, 5, 7, 13, 21} and skier heights {3,4, 7, 11,
18}.
- a summary of how you tested your algorithms and on what
platform (what machine, what speed, what compiler, what IDE, if
any)
- the running times on increasing values of n and m, until the
difference in speed is significant (from seconds to minutes or
more)
- conclusions
The report can be very brief, but
needs to be structured as above.
Enjoy!