(Recurrence)
Given a rectangle of 100*100, we need to divide this area, and the vertical lines have already been divided for you, now you are required to add a horizontal line in this region. The line 1 and the line 1 are required. How to Select a horizontal line can make the most election ranges. Condition of the election interval: There is no vertical line inside, and there is a point inside the interval. Note: the points on the boundary are also included, but it is necessary to prevent repeated calculation into the constituency.
Solution: This question is not so easy to understand, and the complexity is also very high. According to other people's questions: first, DP [I] [J] indicates the number of constituency when the serial number of the I-root crossline is J. S [I] [J] indicates the number of selection zones between the I-root and J-root. Note that to calculate the boundary point, I to J is left closed and right open [I, j) (including the I online point, but does not include vertices on the horizontal line J ). DP [[I] [J] = max (DP [I-1] [k] + s [k] [J ]));
Therefore, we need to pre-process the s [I] [J]: we also need to find a policy for processing. Otherwise, the complexity is very high. Use G [I] [J] [k] To represent whether the I-1 and I-1 bars are selected. G [I] [J] [k] | = G [I] [J-1] [k];
G [I] [J] [k] | = T [J] [k] (whether the J-1 line is between the K-1 and the K vertical line, note that the boundary points of the vertical lines must also be calculated and repeated. Likewise: [k-1, K ).
Code:
# Include <cstdio> # include <cstring> const int n = 105; int n, m; int s [N] [N]; int T [N] [N]; int DP [N] [N]; int P [N] [N]; int Street [N]; int G [N] [N] [N]; int path [N] [N]; int max (const int A, const int B) {return A> B? A: B;} void Init () {memset (T, 0, sizeof (t); For (INT I = 1; I <= 100; I ++) {for (Int J = 1; j <m; j ++) {int K; For (k = Street [J-1]; k <Street [J]; k ++) if (P [I-1] [k]) break; If (K! = Street [J]) T [I] [J] = 1 ;}} memset (G, 0, sizeof (g); memset (S, 0, sizeof (s); For (INT I = 1; I <100; I ++) {for (Int J = 1; j + I <= 100; j ++) {for (int K = 1; k <m; k ++) G [J] [J + I] [k] | = G [J] [J + I-1] [k]; for (int K = 1; k <m; k ++) g [J] [J + I] [k] | = T [J + I] [k]; for (int K = 1; k <m; k ++) if (G [J] [J + I] [k]) s [J] [J + I] ++ ;}} void printf_ans (int, int J) {If (path [a] [J] =-1) return; printf_ans (A-1, path [a] [J]); printf ("% d", path [a] [J]);} int main () {int x, y, a; while (scanf ("% d", & N) & n! =-1) {memset (p, 0, sizeof (p); For (INT I = 0; I <n; I ++) {scanf ("% d", & X, & Y); P [y] [x] = 1;} scanf ("% d", & M ); for (INT I = 0; I <m; I ++) scanf ("% d", & Street [I]); scanf ("% d", & ); init (); DP [1] [1] = 0; path [1] [1] =-1; for (INT I = 2; I <=; I ++) {for (Int J = I; j <= 100; j ++) {DP [I] [J] = 0; if (I = 2) {DP [I] [J] = max (DP [I] [J], DP [1] [1] + s [1] [J]); path [I] [J] = 1 ;}else {for (int K = 2; k <j; k ++) {If (DP [I-1] [k] + s [k] [J]> = DP [I] [J]) path [I] [J] = K; DP [I] [J] = max (DP [I] [J], DP [I-1] [k] + s [k] [J]) ;}}// printf ("% d \ n ", T [50] [1]); printf ("% d", a); printf_ans (A, 100); printf ("100 \ n");} return 0 ;}