Original question connection: http://acm.zju.edu.cn/onlinejudge/showProblem.do? Problemcode = 3209.
I thought of using dancing chains, but I think the principle of dancing chains is to search. How efficient can it be? The data size of this question is 500*30*30. I don't know the time complexity of the dancing chain. I hesitated at will, but I still knocked one side with the dancing chain. I didn't expect 1A, it is important that I never lost a dance chain once, although there is a template
Solution: The Dancing chain solves the problem of selecting several rows so that each column has only one and only one row, select several rectangles so that each coordinate has only one rectangle to overwrite.
I still have a doubt that the matrix of 500*15000 can be a with dancing chains. I want to know how big the matrix can be solved by dancing chains? That is, what is the time complexity?
Let's take a look at the code. I have been calling it for a long time.
# Include <cstdio> # include <cstdlib> # include <cstring> # include <iostream> using namespace STD; # define Max 0x3f3f3f # define size 100005 bool arr [510] [size]; int L [size], R [size], U [size], d [size], col [size], row [size]; // I have not properly analyzed the specific length of each array. // The row where the column is located, int s [size]; // Number of column elements int sel [size], seln; // selected row int Mi; struct dancer {void Init (INT height, int width) {int P/* node number */, X, Y, last; For (P = 1; P <= width; P ++) // initialize the column header pointer {L [p] = p-1; R [p] = p + 1; // left and right adjacent U [p] = d [p] = P; // only one column S [p] = 0; // Number of column elements //} p = width + 1; for (y = 1; y <= height; y ++) // row {last = R [0] = L [0] = 0; // The virtual header pointer for (x = 1; x <= width; X ++) // column {If (ARR [Y-1] [x-1]! = 0) // 0 ~ N-1-> 1 ~ N !!!!!!!!!!!!!!! {// Add to the end of the row linked list l [p] = last; R [last] = P; // Add to the end of the column linked list U [p] = U [x]; d [p] = x; U [x] = d [U [x] = P; // row [p] = Y in the row column of the record; col [p] = x; s [x] ++; last = P ++; }}// remove the virtual header, create a row-loop linked list R [last] = R [0]; L [R [0] = last;} R [width] = 0; L [0] = width; R [0] = 1; s [0] = max;} // Delete the void remove (const Int & C) row where all 1 Elements in Column C are located) {L [R [c] = L [c]; R [L [c] = R [c]; // classic deletion 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] ;}// restore the void resume (const Int & C) of the row where all 1 Elements in Column C are located) {for (INT I = U [c]; I! = C; I = U [I]) for (Int J = L [I]; J! = I; j = L [J]) {u [d [J] = J; d [U [J] = J; ++ s [col [J];} l [R [c] = C; R [L [c] = C; // classic recovery} bool Dance () {If (R [0] = 0) return true; // No int C = 0, I, j; for (I = R [0]; I! = 0; I = R [I]) // find the column C if (s [I] <s [c]) C = I; remove (C ); for (I = d [c]; I! = C; I = d [I]) // Delete the row I {for (j = R [I]; J! = I; j = R [J]) // Delete the column where the row element is located J remove (COL [J]); SEL [seln] = row [I]; // select the row to save the row number seln ++; If (Dance () // for different questions, this location often needs to be changed {mi = min (MI, seln );} seln --; For (j = L [I]; J! = I; j = L [J]) Resume (COL [J]);} resume (c); Return false ;}} DC; int main () {int N, m, P; int t; CIN> T; while (t --) {CIN> N> m> P; memset (ARR, 0, sizeof (ARR); For (int K = 0; k <p; k ++) {int x1, x2, Y1, Y2; cin> x1> Y1> X2> Y2; For (INT I = x1; I <X2; I ++) {for (Int J = Y1; j <Y2; j ++) {arr [k] [I * m + J] = 1 ;}}} /// // seln = 0; mi = 100000; DC. init (p, N * m); DC. dance (); If (MI <100000) {cout <mi <"\ n";} else cout <"-1 "; putchar ('\ n ');}}