User:Jeff/ACM/Zones

Back to ACM page

Zones
Telephone poles are part of an outdated technology. Cell phones nowadays allow us to call whoever we want, wherever we want, independent of any wire. There is one problem -- without a service tower nearby a cell phone is useless.

In the absense of hills and mountains, a service tower will provide coverage for a circular area. Instead of planning where to place the wires, a wireless telephone company has to plan where to build its service towers. Building the towers too far apart causes holes in the coverage and increases complaints. Building the towers too close to each other results in large areas covered by more than one tower, which is redundant and inefficient.

International Cell Phone Company is developing a network strategy to determine the optimal placement of service towers. Since most customers have replaced their old wired home phones by cell phones, the strategy for planning service towers is therefore to cover as many homes of customers as possible.

The figure below shows the service areas for the five towers ICPC's strategic department planned to build this year. Tower 5 will serve 24 customers, 6 of which are also served by tower 4. Towers 1, 2 and 3 have a common service area containing 3 customers.



Shortly after the plans for these five towers had been published, higher management issued a stop on all tower building. Protesting customers forced them to weaken this decree, and allow the building of three towers out of the five planned. These three towers should serve as many customers as possible, of course. Finding the best possible choice for the towers to build is not trivial (the best choice in this case is towers 2, 4 and 5, serving 68 customers).

You must write a program to help ICPC choose which towers to build in cases like these. If several choices of towers serve the same number of customers, choices including tower 1 are preferable. If this rule still leaves room for more than one solution, solutions including tower 2 are preferable, and so on.

Input
The input file contains several test cases. The first line of each test case contains two positive integers: the number n (n &le; 20) of towers planned, and the number of towers to be actually built. The next line contains n numbers, each giving the number of customers served by a planned tower. (The first number refers to the first tower, and so on.) No tower serves more than a million people. The next line contains the number m (m &le; 10) of common service areas. Each of the next m lines contains the description of a common service area. Such a line starts with the number t (t > 1) of towers for which this is a common service area, followed by the t numbers of towers. The last number on the line is the number of customers in the common service area. The last line of the input file consists of the two integers 0 0.

Output
For each test case, display the number of customers served and the best choice for the locations of the towers. Follow the format of the sample output.

Analysis
Given n towers, we must find the subset of a specified size with the greatest value, using a lexicographical tiebreaker rule. Since n is at most 20, we can generate and test each possibility using bitmasks. Therefore, this problem reduces to calculating the number of customers that would be served by a specific subset of towers.

To see how we might calculate this number, let's use the example diagram to calculate the number of customers served by towers 1, 2 and 3. Counting the individual regions by hand yields 5+7+8+3+2+15+5=45 total customers. If we were to simply sum the totals for each tower, we would get 15+20+25=60 customers. However, this number includes the regions of size 7 and 2 twice each, and the region of size 3 three times. By subtracting these extra additions, we get 60-7-2-3-3=45, the previously calculated answer. This algorithm can be generalized as follows: for each tower in the set we're considering building, add up the total number of customers it serves. Then, for each common service area, count the number of considered towers it includes (call this number x). If x > 1, we multiply the number of customers in this common service area by (x-1), which is the number of extra times these people have been counted, and subtract this product from our total.

Source code
using namespace std; pair solve(vector, int, vector , vector ); int main { for (int i(1); ; ++i) { int n, toBuild; cin >> n >> toBuild; if (n == 0) return 0; vector towerPop(n); for (int j(0); j < n; ++j) cin >> towerPop[j]; int m;    cin >> m;     vector areaMask(m, 0), areaPop(m); for (int j(0); j < m; ++j) { int t;      cin >> t;       for (int k(0); k < t; ++k) { int x;        cin >> x;         areaMask[j] |= (1<<(x-1)); }      cin >> areaPop[j]; }    pair ans(solve(towerPop, toBuild, areaMask, areaPop)); if (i > 1) cout << endl; cout << "Case Number "< solve(vector towerPop, int toBuild,    vector areaMask, vector areaPop) { int n(towerPop.size), m(areaMask.size); int maxCust(0), bestMask(0); for (int i(0); i < (1< 1) tempPop -= areaPop[j]*(tempCount-1); }    if (tempPop > maxCust) { maxCust = tempPop; bestMask = i;    } }  vector ans; for (int i(0); i < n; ++i) { if (bestMask & (1<<(n-i-1))) continue; ans.push_back(i+1); }  return make_pair(maxCust, ans); }
 * 1) include
 * 2) include