import java.util.Scanner;
import java.util.Arrays;
public class Main {
static int[][] a;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
a = new int[90][100010];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m ; j++) {
a[i][j] = sc.nextInt();
}
}
int limit = sc.nextInt();
int ans = 0;
// 直接暴力
for (int i = 1; i <= n ; i++) { //左上角y坐标
for (int j = 1; j <= m ; j++) { // 左上角x坐标
for (int l = i; l <= n; l++) { // 左下角
int maxl = Integer.MAX_VALUE;
int maxr = Integer.MAX_VALUE;
for (int r = j; r <= m ; r++) { // 右下角
// 先打印下标看遍历的对不对
// System.out.println( "i:"+i+" j:"+j+" l:"+l+" r:"+r);
//运行超时,做个剪枝,得出答案后小于这个答案的子矩阵都不用看了
//还有10个超时,再做个剪枝,如果子矩阵内稳定性大于limit了,那么比它大的子矩阵稳定性也必定超过limit
if((r-j+1)*(l-i+1) <= ans || l >= maxl || r >= maxr){
continue;
}
// 计算子矩阵稳定性
if(count(i,j,l,r) <= limit){
//计算子矩阵面积
int num = (r-j+1)*(l-i+1);
if(ans < num) ans = num;
}else {
// 子矩阵的稳定性超过limit了,标记一下当前子矩阵大小,也就是左下角和右下角的下标
maxl = l;
maxr = r;
break;
}
}
}
}
}
System.out.println(ans);
}
static int count(int i,int j ,int l,int r){
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for (int x = i; x <= l; x++) {
for (int y = j; y <= r ; y++) {
max = Math.max(max,a[x][y]);
min = Math.min(min,a[x][y]);
}
}
return max-min;
}
}
没用二分+双指针,
用的暴力+剪枝:
剪枝1:得出答案后,小于这个面积的子矩阵都不用看了
剪枝2:如果子矩阵内稳定性大于limit了,那么在左上角确定的情况下,比它大的子矩阵稳定性也必定超过limit