Assignments | Class Photo | Computing Resources | Course Home | Lab Hours/Tutoring | Schedule | Submit

Saint Louis University

Computer Science 180
Data Structures

Michael Goldwasser

Spring 2009

Dept. of Math & Computer Science


Lab Assignment 11

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.


Bulletin Board

posters

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 < xhw, and 0 ≤ yl < yhh.

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



Hints

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:

  1. Initialize

    1. Create a priority queue
          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.

    2. Initialize a sweepline
          vector sweepline(w,0);
      that 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.

    3. Declare and initialize two extra variables sweepingZero and sweepingMax that keep track of the number of entries of the sweepline that are respectively equal to zero, or equal to the global maximum depth. Maintaining these variables will save time in avoiding the need to later loop through the sweepline vector to count such totals.

    4. Declare and initialize variables for the three output values (the uncovered area, maximum depth, and area achieving maximum depth). Because the grid is so large, please use long as your data type for the area calculations.

  2. Sweep.

      While there are still events in the queue, process the next one.

    1. First, make sure to account for the motion of the sweepline from the previous event to this one. You may have been sweeping over some uncovered area as well as some maximally covered areas. Use the variables sweepingZero and sweepingMax, together with your knowledge of the previous and current y-coordinates.

    2. If you are entering a new poster, increase the sweepline depth for each entry in the range [xl,xh).

      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 "area with maximum depth" back to zero (that previously swept area with lesser depth is no longer relevant).


    3. If you are leaving an existing poster, decrease the sweepline depth for each entry in the range [xl,xh).

      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.


  3. Finalize.

      You're past all of the posters. However, if the sweepline is not already at the bottom of the bulletin board, then you will need to account for the final piece of uncovered board before outputting your results.

Michael Goldwasser
CSCI 180, Spring 2009
Last modified: Saturday, 18 April 2009
Assignments | Class Photo | Computing Resources | Course Home | Lab Hours/Tutoring | Schedule | Submit