Saint Louis University |
Computer Science 180
|
Dept. of Math & Computer Science |
Topic: | Bulletin Board |
Source Code: | bulletin.cpp |
Live Archive Ref#: | 4171 |
In-Class Day: |
Tuesday, 21 April 2009 |
Submission Deadline: | Friday, 24 April 2009, 11:59pm |
Techniques: |
Priority Queue, Sweepline Algorithm |
Please review the general information about lab assignments.
The ACM Student Chapter has just been given custody of a number of school bulletin boards. Several members agreed to clear off the old posters. They found posters plastered many levels deep. They made a bet about how much area was left clear, what was the greatest depth of posters on top of each other, and how much of the area was covered to this greatest depth. To determine each bet's winner, they made very accurate measurements of all the poster positions as they removed them. Because of the large number of posters, they now need a program to do the calculations. That is your job.
A simple illustration is shown above: a bulletin board 45 units wide by 40 high, with three posters, one with corners at coordinates (10, 10) and (35, 20), another with corners at (20, 25) and (40, 35), and the last with corners at (25, 5) and (30, 30). The total area not covered by any poster is 1300. The maximum number of posters on top of each other is 2. The total area covered by exactly 2 posters is 75.
Input: The input will consist of one to twenty data sets, followed by a line containing only 0. On each line the data will consist of blank separated nonnegative integers.
The first line of a dataset contains integers n w h, where n is the number of posters on the bulletin board, w and h are the width and height of the bulletin board. Constraints are 0 < n ≤ 100; 0 < w ≤ 50000; 0 < h ≤ 50000.
The dataset ends with n lines, each describing the location of one poster. Each poster is rectangular and has horizontal and vertical sides. The x and y coordinates are measured from one corner of the bulletin board. Each line contains four numbers xl yl xh and yh, where xl and yl, are the lowest values of the x and y coordinates in one corner of the poster and xh and yh are the highest values in the diagonally opposite corner. Each poster fits on the bulletin board, so 0 ≤ xl < xh ≤ w, and 0 ≤ yl < yh ≤ h.
Output: There is one line of output for each data set containing three integers, the total area of the bulletin board that is not covered by any poster, the maximum depth of posters on top of each other, and the total area covered this maximum number of times.
Caution: An approach examining every pair of integer coordinates might need to deal with 2 billion coordinate pairs.Example input: | Example output: |
3 45 40 10 10 35 20 20 25 40 35 25 5 30 30 1 20 30 5 5 15 25 2 2000 1000 0 0 1000 1000 1000 0 2000 1000 3 10 10 0 0 10 10 0 0 10 10 0 0 10 10 0 |
1300 2 75 400 1 200 0 1 2000000 0 3 100 |
Although there are several ways to solve this problem, we ask you to use an approach known as a "sweepline" algorithm. We scan the bulletin board from top to bottom, always keeping track of the current number of posters under a particular [x,x+1) region of the sweepline. As long as those numbers remain the same as we sweep, it is easy to calculate how much uncovered (i.e. zero-depth) area is being swept past, as well as how much of the area has the maximum depth thus far. The only change to those depths will occur when we sweep past the top of a new poster, or past the bottom of a current poster.
However, with a 50000 x 50000 grid, we cannot afford to move the sweepline one unit at a time along the y-axis. Instead, we want to find the significant events, namely times when we cross over the top or bottom of a poster. We will use a priority queue to manage such events. For your convenience, we have already defined the following simply structure for representing an event.
struct Event { int xl; int yl; int xh; int yh; bool entering; Event(int xl, int yl, int xh, int yh, bool entering) : xl(xl), yl(yl), xh(xh), yh(yh), entering(entering) { } // in case of tie, we want to EXIT rectangles before we ENTER new ones bool operator<(const Event& other) const { int y = (entering ? 2*yh-1 : 2*yl+1); int otherY = (other.entering ? 2*other.yh-1 : 2*other.yl+1); return (y < otherY); } };We have carefully defined the < operator so that a priority queue will return the event with the greatest y-cordinate, and in case of a tie, processing the event of leaving one rectangle before the event of entering another (because we don't want it to appear as if two posters are simultaneously covering such a boundary point).
Your job is to do the simulation, computing the desired information. Here is an outline of the process:
prority_queue<Event> pq;For each poster, add two events into the priority queue: one for entering the top of the poster and one for leaving the bottom.
vectorthat can be used to maintain the current depth for each unit along the x-dimension. It is initialized so as to have width w, and with all entries initially set to zero.sweepline(w,0);
While doing so, make sure to account for any changes in the
number of zeros under the sweepline, or the number of
entries equal to the maximum depth.
If you find yourself surpassing the previous maximum depth,
record the new depth and then set the
Again, make sure to account for any changes in the number of zeros under the sweepline, or the number of entries equal to the maximum depth.