Treasure Map Time Limit: 2 seconds memory limit: 32768 KB

Your boss once had got extends copies of a treasure map. unfortunately, all the copies are now broken to your rectangular pieces, and what make it worse, he has lost some of the pieces. luckily, it is possible to figure out the position of each piece in the original map. now the boss asks you, the talent programmer, to make a complete treasure map with these pieces. you need to make only one complete map and it is not necessary to use all the pieces. but remember, pieces are not allowed to overlap with each other (see sample 2 ).

**Input**

The first line of the input contains an integer*T*(*T*<= 500), indicating the number of instances.

For each case, the first line contains three Integers*N m p*(1 <=*N*,*M*<= 30, 1 <=*P*<= 500), the width and the height of the map, and the number of pieces. Then*P*Lines follow, each consists of four Integers*X1 Y1 X2 Y2*(0 <=*X1*<*X2*<=*N*, 0 <=*Y1*<*Y2*<=*M*), Where (x1, Y1) is the coordinate of the lower-left corner of the rectangular piece, and (X2, Y2) is the coordinate of the upper-right corner in the original map.

Cases are separated by one blank line.

**Output**

If you can make a complete map with these pieces, output the least number of pieces you need to achieve this. If it is impossible to make one complete map, just output-1.

**Sample Input**

35 5 10 0 5 55 5 20 0 3 52 0 5 530 30 50 0 30 100 10 30 200 20 30 300 0 15 3015 0 30 30

**Sample output**

1-12

**Hint**

For sample 1, the only piece is a complete map.

For sample 2, the two pieces may overlap with each other, so you can not make a complete treasure map.

For sample 3, you can make a map by either use the first 3 pieces or the last 2 pieces, and the latter approach one needs less pieces.

Author: Hang, Hang

Source: The 6th Zhejiang Provincial Collegiate Programming Contest

Solution:

Given a n * m large rectangle, then given a p small rectangle, given the coordinates of the upper left corner and the upper right corner, ask if you can take out some large rectangles that completely overwrite the given ones from these small rectangles. You must not cross them when they are covered. If you can, find the minimum number of small rectangles required, otherwise, output-1.

This question can be converted to the full coverage problem of DLX, and the 01 matrix is constructed. How to construct it? First, we regard each of the given P small rectangles as a row. Then the constructed matrix has P rows. The original N * m large rectangles can be divided into N * m small cells, each cell is regarded as a column, and each cell has a number (1-N * m). To completely overwrite this large rectangle, all grids numbered 1-N * m should be 1 (overwritten ). if the constructed matrix has n * m columns, a new matrix of P rows and N * m columns is constructed. The next step is to split each small rectangle into a 1*1 small grid, which is projected into the grid inside the corresponding row respectively (the grid is set to 1 ), the POS [I] [J] array is used to record the coordinates in the next large rectangle as I. The number of the small lattice of J in the large rectangle is, when each line is projected, based on the coordinates of the small rectangle, the two loops route the small grids one by one to the row (that is, find the column corresponding to the row of each small grid ). After all the P small rectangles are projected to the corresponding rows, the 01 matrix is converted to the number of rows to be extracted, each column in the new matrix composed of these rows has a 1 (because the column number is 1-N * m, and the small lattice Number of the large rectangle is also 1-N * m, to completely overwrite, each column must have 1), and each column has only 1 (because two small rectangles cannot be crossed ). after converting the number, you can use DLX to solve the problem. It is not feasible to apply a template only. If the template is found, it will be returned. If this question is the smallest one, you have to continue searching after finding an answer and cannot return it.

Code:

# Include <iostream> # include <stdio. h> using namespace STD; const int maxnode = 450010; const int maxm = 901; const int maxn = 505; struct DLX {int n, m, size; int U [maxnode], d [maxnode], R [maxnode], L [maxnode], row [maxnode], Col [maxnode]; int H [maxn]; // The row header node int s [maxm]; // number of nodes in each column int anSd, ANS [maxn]; // if there is an answer, select anSd, which Rows are placed in the ANS [] array? Ans [0 ~ Ansd-1]; void Init (INT _ n, int _ m) {n = _ n, m = _ m; For (INT I = 0; I <= m; I ++) {s [I] = 0; U [I] = d [I] = I; // In the initial state, up and down to self L [I] = I-1; R [I] = I + 1;} R [m] = 0, L [0] = m; size = m; // ID. Each column has a head node numbered 1-m for (INT I = 1; I <= N; I ++) H [I] =-1; // header node of each row} void Link (int r, int c) // row R, column C {++ s [col [++ size] = C]; // The column where the node of the size is located is C, number of nodes in the current column + + row [size] = r; // The row location of the node in the size column is r d [size] = d [c]; // Insert the following four statements (the figure is inverted ?) U [d [c] = size; U [size] = C; d [c] = size; If (H [R] <0) H [R] = L [size] = R [size] = size; else {R [size] = R [H [R]; L [R [H [R] = size; L [size] = H [R]; R [H [R] = size ;}} void remove (INT c) // delete node C, and the row where the upper and lower nodes of node C are located. Each time this function is called, it is deleted from the column header node down, here C can also be understood as column c {// because the column header node in Column C is numbered c l [R [c] = L [c]; R [L [c] = R [c]; for (INT I = d [c]; I! = C; I = d [I]) for (Int J = R [I]; J! = I; j = R [J]) {u [d [J] = U [J]; d [U [J] = d [J]; -- s [col [J] ;}} void resume (INT c) // restore node C, and the row where the upper and lower nodes of C are located (same as above, it can also be understood as restoring {for (INT I = U [c]; I from the header node of column C! = C; I = U [I]) for (Int J = L [I]; J! = I; j = L [J]) + + s [col [U [d [J] = d [U [J] = J]; // This line is too tangled t l [R [c] = R [L [c] = C;} void Dance (int d) // recursive depth {If (anSd! =-1 & anSd <= d) // the minimum number of rows. A group of answers anSd <= D have been found before. Currently, you do not need to recursively look for return; if (R [0] = 0) {If (anSd =-1) anSd = D; else if (d <anSd) // The minimum number of anSd = D; return;} int c = R [0]; for (INT I = R [0]; I! = 0; I = R [I]) if (s [I] <s [c]) C = I; remove (c); // locate the column with the least number of nodes, the current element is not a node 0, 1 on the source image, but a column header node for (INT I = d [c]; I! = C; I = d [I]) {ans [d] = row [I]; // a node under the column header node for (Int J = R [I]; j! = I; j = R [J]) Remove (COL [J]); Dance (D + 1); // locate, return for (Int J = L [I]; j! = I; j = L [J]) Resume (COL [J]) ;}resume (c) ;}; DLX X; int n, m; int P, X1, y1, X2, Y2; int POS [32] [32]; // The Int ID of each cell in each rectangle; void getpos (int n, int m) {id = 1; for (INT I = 1; I <= N; I ++) for (Int J = 1; j <= m; j ++) pos [I] [J] = ID ++;} int main () {int t; scanf ("% d", & T); While (t --) {scanf ("% d", & N, & M, & P); X. init (p, N * m); getpos (n, m); For (INT r = 1; r <= P; r ++) {scanf ("% d", & X1, & Y1, & X2, & Y2); For (INT I = X1 + 1; I <= x2; I ++) for (Int J = Y1 + 1; j <= Y2; j ++) X. link (R, POS [I] [J]);} X. anSd =-1; X. dance (0); printf ("% d \ n", X. anSd);} return 0 ;}

[ACM] zoj 3209 treasure map (precise coverage of dancing links, rectangular coverage)