Question link: http://acm.zju.edu.cn/onlinejudge/showProblem.do? Problemcode = 3616.
N, m, B, G (0 <n <= 100, 0 <m <= 2000, 0 <B, G <= m * n, there are 2 * m numbers in each row in the N rows below. The first number represents the contribution of a student to the chorus, and the second number represents the gender of the student, B and G indicate at least the number of boys and girls in a rectangle. Find a rectangle to maximize the contribution to the chorus and the contribution to the chorus is not negative.
When I first saw this question, the idea was to find a special point (the x-axis or Y-axis separated by the points with the contribution value of-1 ), then we traverse the Split points and find the time complexity is O (M * m). The process of finding contribution can be O (1), and the maximum number of M may be 20000, so it is a wrong idea.
The problem is as follows:
The data range given in the question is 100 rows and 2000 columns with few rows. Therefore, you can consider the brute-force enumeration of the number of rows of the Child matrix (the starting and ending rows), and then start enumeration from the first column, until a negative number occurs in a column, calculate the sum between the number and the previous column that appears negative, determine whether the number of men and women meets the requirements, and then update the answer.
# Include <iostream> # include <stdio. h> using namespace STD; int n, m, B, G; int num [105] [2005], sex [105] [2005]; int girl [105] [2005], BOY [105] [2005]; int c1 [105] [2005], sum [105] [2005]; void Init () {for (INT I = 1; I <= N; I ++) for (Int J = 1; j <= m; j ++) scanf ("% d", & num [I] [J], & sex [I] [J]), sex [I] [J] --; for (INT I = 1; I <= N; I ++) sum [I] [0] = 0, girl [I] [0] = 0, boy [I] [0] = 0, c1 [I] [0] = 0; For (Int J = 1; j <= m; j ++) sum [0] [J] = 0, girl [0] [J] = 0, BOY [0] [J] = 0, c1 [0] [J] = 0; For (INT I = 1; I <= N; I ++) for (Int J = 1; j <= m; j ++) {sum [I] [J] = sum [I-1] [J] + sum [I] [J-1]-sum [I-1] [J-1] + num [I] [J]; girl [I] [J] = Girl [I-1] [J] + girl [I] [J-1]-girl [I-1] [J-1] + sex [I] [J]; boy [I] [J] = boy [I-1] [J] + boy [I] [J-1]-boy [I-1] [J-1] + (! Sex [I] [J]); c1 [I] [J] = c1 [I-1] [J] + c1 [I] [J-1]-c1 [I-1] [J-1] + (Num [I] [J] <0 );}} bool judge (int s, int T, int col) {// judge in the col column, -1 return c1 [T] [col]-c1 [s-1] [col]-c1 [col]-c1 [T] [col-1] + c1 [s-1] from row s to row T [col-1];} int calc (int s, int T, int pre, int now) {return sum [T] [now]-sum [s-1] [now]-sum [T] [pre-1] + sum [s-1] [pre-1];} bool OK (INT S, int T, int pre, int now) {return (BOY [T] [now]-boy [s-1] [now]-boy [T] [pre-1] + boy [S-1] [pre-1])> = B & (GIRL [T] [now]-girl [s-1] [now]-girl [T] [pre-1] + girl [s-1] [pre-1])> = g);} int main () {While (~ Scanf ("% d", & N, & M, & B, & G) {Init (); int ans = 0; for (INT I = 1; I <= N; I ++) {for (Int J = I; j <= N; j ++) {int pre = 0; for (int K = 1; k <= m; k ++) if (Judge (I, j, k) {If (k = 1 | judge (I, j, k-1) Pre = K; else {int S = calc (I, j, pre + 1, k-1); If (S> ans & OK (I, j, pre + 1, k-1) ans = s; Pre = K ;}} if (! Judge (I, j, m) {int S = calc (I, j, pre + 1, m); If (S> ans & OK (I, j, pre + 1, m) ans = s ;}} if (ANS! = 0) printf ("% d \ n", ANS); else puts ("no solution! ");}}Preprocessing and enumeration are highlights.
Zoj 3616 choir III [violent thoughts]