import java.util.Scanner;
public class A020_边界为1的最大子方阵 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = 6;
int n = 6;
int[][] arr = new int[m][n];
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
arr[i][j] = sc.nextInt();
int min = n;
if (min > m)
min = m;
int ans = MaxChild(arr, min);
System.out.println(ans);
}
private static int MaxChild(int[][] arr, int min) {
while (min > 0) {
l2: for (int i = 0; i < arr.length; i++) {
int a = min + i - 1;
if (a >= arr.length)
break;
l3: for (int j = 0; j < arr[i].length; j++) {
int b = min + j - 1;
if (b >= arr[i].length)
continue l2;
int x = i;
int y = j;
while (y < min + j) {// 上
if (arr[x][y] == 0)
continue l3;
y++;
}
y--;
while (x < min + i) {// 右
if (arr[x][y] == 0)
continue l3;
x++;
}
x--;
while (y >= j) {// 下
if (arr[x][y] == 0)
continue l3;
y--;
}
y++;
while (x >= i) {// 左
if (arr[x][y] == 0)
continue l3;
x--;
}
return min;
}
}
min--;
}
return 0;
}
}
输入就不讲啦,首先介绍main函数里的变量:
- min:矩阵中的最小值,也就是可以求出的最大子矩阵的边长;
- ans:是最后求出的答案;
- MaxChild:是该题的核心方法,传入数组和边长;
然后介绍核心方法MaxChild里的内容:
- 最外层的while循环,是计入最大边长;
- 第一个for循环和第二个for循环就是遍历矩阵的行和列;
- 然后这里做了两个提前“剪枝”,分别是变量a和变量b,两个变量都-1,是因为和数组的下标有关,如上所述,min是要求的边长,并且是在变化的,如果现在这个下标,加上要求的边长越界的话,那就直接continue或者退出了;
- 然后接下来是x和y两个变量,分别是复制了i和j的值,以便于做接下来的4个循环;
- 四个循环就不分别介绍了,注释上有,分别是走上、右、下、左,这4条边,这边就举一个例子,比如走的是上面这条边,min+j的意思,就是说要求的边长加上现在下标的位置,这里不用担心越界,因为如果越界的话,前面已经剪枝,剪掉了,然后就会走循环里的内容,也就是从左往右的这个行,碰到0就会返回,如果没碰到,就会一直走下去,那么之后的y–的意思,是因为while循环走完后,如果没有continue,那么y是越界状态的,需要–;让它回来。如果这4个点,都能走到最后,那就说明这个边长的矩阵,就是最大矩阵了,直接return就好了。