子矩阵问题
Description
给定一个矩形区域,每一个位置上都是1或0,求该矩阵中每一个位置上都是1的最大子矩形区域中的1的个数。
Input
输入第一行为测试用例个数。每一个用例有若干行,第一行为矩阵行数n和列数m,下面的n行每一行是用空格隔开的0或1。
Output
输出一个数值。
Sample Input 1
1 3 4 1 0 1 1 1 1 1 1 1 1 1 0
Sample Output 1
6
解题步骤:
计录单个点左边的连续1的数量,和上边的连续1的数量。
对于每一个点,该点左边连续的1数量为w(宽),然后可以从该点出发往上一直找到0为止。实时更新w,然后计算面积。如下图所示:
完整实现代码如下:
1 import java.util.*; 2 public class Main { // 注意类名必须为Main 3 4 public static void main(String[] args) { 5 Scanner scan = new Scanner(System.in); 6 int x = scan.nextInt(); 7 scan.nextLine(); 8 // n个测试样例 9 for (int k = 0; k < x; k++){ 10 int n = scan.nextInt(); 11 int m = scan.nextInt(); 12 int[][] arr = new int[n][m]; 13 for (int i = 0; i < n; i++) { 14 for (int j = 0; j < m; j++) { 15 arr[i][j] = scan.nextInt(); 16 } 17 } 18 // 计算每个点左边和上面连续1的个数 19 int[][] leftNum = new int[n][m]; 20 int[][] topNum = new int[n][m]; 21 for (int i = 0; i < n; i++) { 22 for (int j = 0; j < m; j++) { 23 if (i == 0) topNum[i][j] = arr[i][j]; 24 else topNum[i][j] = arr[i][j] != 0 ? topNum[i-1][j] + 1 : 0; 25 if (j == 0) leftNum[i][j] = arr[i][j]; 26 else leftNum[i][j] = arr[i][j] != 0 ? leftNum[i][j-1] + 1 : 0; 27 } 28 } 29 // 计算最大面积 30 int max = 0; 31 for (int i = 0; i < n; i++) { 32 for (int j = 0; j < m; j++) { 33 if (arr[i][j] == 0) continue; 34 int w = leftNum[i][j];; 35 int sum; 36 int top = i + 1 - topNum[i][j]; 37 for (int p = i; p >= top; p--) { 38 // 更新宽度 39 w = Math.min(w, leftNum[p][j]); 40 sum = w*(i-p+1); 41 max = Math.max(max,sum); 42 } 43 } 44 } 45 System.out.println(max); 46 } 47 } 48 49 }