Full 1 sub-matrix with the largest area -- 9 degrees OJ 1497, oj1497
-
Description:
-
In an M * N matrix, all the elements are only 0 and 1. From this matrix, we can find a fully-1 sub-matrix with the largest area. The maximum is the maximum number of element 1.
-
Input:
-
The input may contain multiple test examples.
For each test case, the first line of input is two integers m, n (1 <= m, n <= 1000): represents the size of the matrix to be input.
There are m rows in the Matrix. Each row has n integers, which are 0 or 1 respectively. The adjacent two numbers are strictly separated by a space.
-
Output:
-
For each test case, the number of elements in the full matrix with the largest area in the output matrix is 1.
-
Sample input:
-
2 20 00 04 40 0 0 00 1 1 00 1 1 00 0 0 0
-
Sample output: 0 4
Problem-solving ideas: Reproduced from http://www.cnblogs.com/fstang/archive/2013/05/19/3087746.html
The method is:
1. First read the 0/1 matrix into x, and update each non-zero element x [I] [j], the number of consecutive 1 above it + 1 (+ 1 indicates calculating itself)
For example, if a row is 0 1 1 0 1 1 1 1 1, update to 0 1 2 0 1 2 3
2. For each non-zero element x [I] [j], scan the column j up and down until a number smaller than itself exists. If row y is scanned, then, we obtain a full 1 sub-matrix (+ 1 represents the row where it is located) of x [I] [j] * (y + 1)
For example, if a column is [0 3 4 3 5 2 1] '(for convenience, the column is represented as a column vector), we process the 4th elements of the column, that is, 3. It can scan two elements up and one element down to get a 4x3 full 1 sub-matrix.
3. Take the largest of these values.
The idea is roughly shown in figure (0 in the blank space is not marked)
In the example given in step 2, the blue arrow indicates scanning up and down, and the black box indicates the final full 1 sub-matrix.
Why is this correct?
Think about it. Can this method be used to find the largest all-1 sub-matrix? -- Certainly.
One of the most complete 1-Child matrices must be that each of the four boundaries cannot be expanded, as shown in
Assume that the first sub-matrix in the figure is the largest sub-matrix, then the column on the left side of the left boundary must have one or more zeros (otherwise, you can expand a column to the left side to obtain a larger all-1 matrix)
The other three boundaries are similar.
Then we can see the 1 marked with a black circle in the figure (which is characterized by the same line as a 0 on the left side of the left border). Starting from this 1, follow the previous method to scan up and down, you can obtain this sub-matrix. So, you can certainly find it.
The following is my code. In actual implementation, we estimated upperbound to improve efficiency. This upperbound is: in the current column,
The sum of consecutive non-zero sequences containing x [I] [col]. For example, for a column [0 3 4 3 5 2 1] ', the next six upperbound columns are all
3 + 4 + 3 + 5 + 2 + 1 = 18. For 0 elements, upperbound is not required.
1 # include <iostream> 2 using namespace std; 3 4 int main () 5 {6 int n, m; 7 while (cin> n> m) {8 int ** array = new int * [n]; 9 int ** upperbound = new int * [n]; 10 for (int I = 0; I <n; I ++) {11 array [I] = new int [m]; 12 upperbound [I] = new int [m]; 13 for (int j = 0; j <m; j ++) {14 cin> array [I] [j]; 15 upperbound [I] [j] = 0; 16} 17} 18 // prepare: 19 for (int I = 0; I <n; I ++) {20 for (int j = 1; j <m; j ++) {21 if (array [I] [j] = 1 & array [I] [J-1]! = 0) array [I] [j] = array [I] [J-1] + 1; 22} 23} 24 // calculate upperbound25 for (int j = 0; j <m; j ++) {26 for (int I = 0; I <n; I ++) {27 if (array [I] [j] = 0) continue; 28 else {29 int sum = 0, temp = I; 30 while (temp <n & array [temp] [j]> 0) {31 sum + = array [temp] [j]; 32 temp ++; 33} 34 for (int k = I; k <temp; k ++) {35 upperbound [k] [j] = sum; 36} 37 I = temp; 38} 39} 40} 41 42 int maxarea = 0; 43 for (int I = 0; I <n; I ++) {44 for (int j = 0; j <m; j ++) {45 if (array [I] [j]! = 0 & maxarea <upperbound [I] [j]) {46 int cnt = 1, val = array [I] [j]; 47 for (int row = I-1; row> 0; row --) {48 if (array [row] [j]> = val) cnt ++; 49 else50 break; // here you must break51} 52 for (int row = I + 1; row <n; row ++) {53 if (array [row] [j]> = val) cnt ++; 54 else55 break; // here must be break56} 57 if (cnt * val> maxarea) maxarea = cnt * val; 58} 59} 60} 61 cout <maxarea; 62} 63 return 0; 64 65}View Code