题目描述:
小明有一个大小为N×M的矩阵,可以理解为一个N行M列的二维数组。 我们定义一个矩阵m 的稳定度f(m)
为f(m)=max(m)-min(m)。 其中max(m)表示矩阵m中的最大值,min(m) 表示矩阵m 中的最小值。
现在小明想要从这个矩阵中找到一个稳定度不大于limit 的子矩阵; 同时他还希望这个子矩阵的面积越大越好(面积可以理解为矩阵中元素个数)。
子矩阵定义如下:
从原矩阵中选择一组连续的行和一组连续的列,这些行列交点上的元素组成的矩阵即为一个子矩阵。
输入格式:
第一行输入两个整数N,M,表示矩阵的大小。 接下来N 行,每行输入M 个整数,表示这个矩阵。 最后一行输入一个整数limit,表示限制。

对于所有评测用例,0≤矩阵元素值, limit≤10^5。
输出格式:
输出一个整数,分别表示小明选择的子矩阵的最大面积。
输入样例:
3 4
2 0 7 9
0 6 9 7
8 4 6 4
8
输出样例:
6
数据范围与提示
满足稳定度不大于8 的且面积最大的子矩阵总共有三个,他们的面积都是6(粗体表示子矩阵元素):
2 0 7 9
0 6 9 7
8 4 6 4
2 0 7 9
0 6 9 7
8 4 6 4
2 0 7 9
0 6 9 7
8 4 6 4
解题思路:
本题采用dfs + 回溯的思想来解决,也就是朴素的暴搜。
若要利用好深搜索得先搞清以下问题:
1.应先明确遍历的起点:
数组中每个元素都可以是起点,这样能无死角地找到所有符合条件的子矩阵。 所以我们要对数组内每个点都进行遍历,不断更新面积最大值。
2.如何知道我们遍历过的符合条件的区域是一个矩阵?(这是我们更新子矩阵面积所必需要知道的。)

“对号”部分是是我们遍历过的区域。
很明显这不是一个矩阵,但是若我们知道遍历过的点的横坐标范围,和纵坐标的范围,问题就解决了。

知道范围后,在这个范围内(即蓝色区域内)遍历一下看看是不是所有点都被遍历过,是则满足子矩阵,否则不满足,这需要单独构建一个布尔数组,和一个判断是否为矩阵的函数。
3.遍历规则:
我们知道 深度优先遍历是一个路径,而我们想要的是子矩阵。
即如果我么们给的限制条件只是在数组区间内遍历,那么它就会在这个区间乱窜。所以我么们需要施加新条件来限制它的遍历轨迹,确保以遍历子矩阵为优先。
即,如果当前遍历路径不是子矩阵的话,我们就将当前所在矩阵区域遍历满。如果当前遍历区域是一个子矩阵的话,我们就扩大边界,试着去得到面积更大的符合条件的子矩阵。
4.遍历过程的模拟:
理清思路后我们可以模拟一下遍历过程,以确保万无一失。想学好 dfs 会模拟自己写的程序是必不可少的。
以题目中例1的遍历为例以下是我的模拟过程,可以助于理解:



理论成立代码如下:
import java.util.Scanner;
public class Main {
public static int n = 0;
public static int m = 0;
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
int a[][] = new int[n + 10][m + 10];//储存数组
visit = new boolean[n][m];
for(int i = 0; i < n; i ++)
for(int j = 0; j < m; j ++) a[i][j] = sc.nextInt();
f = sc.nextInt();
for(int i = 0; i < n; i ++)
for(int j = 0; j < m; j ++) {
mini = i;
minj = j;
maxi = i;
maxj = j;
sunmatrix = 1;
minvalue = a[i][j];
maxvalue = a[i][j]; // 初始化
visit[i][j] = true;//标记
dfs(a, i, j);
visit[i][j] = false;//回溯
maxsmatrix = Math.max(sunmatrix, maxsmatrix);//更新
}
System.out.print(maxsmatrix);//最终结果
}
public static boolean visit[][];//储存路径
public static int mini = 0;
public static int maxi = 0;
public static int minj = 0;
public static int maxj = 0;//储存矩阵范围
public static int f = 0;//储存题目要求稳定度
public static int minvalue = 0;
public static int maxvalue = 0;//储存遍历过的路径最大值与最小值
public static int sunmatrix = 0;//储存每次遍历最大面积
public static int maxsmatrix = 0; // 储存最终答案
public static void updatemx(int i, int j) {//更新遍历的矩阵范围
mini = Math.min(mini, i);
minj = Math.min(minj, j);
maxi = Math.max(maxi, i);
maxj = Math.max(maxj, j);
}
public static int F(int value) {//判断矩阵稳定度
minvalue = Math.min(minvalue, value);
maxvalue = Math.max(maxvalue, value);//更新
return maxvalue - minvalue;
}
public static void dfs(int a[][], int i, int j) {
if(ifmatrix() && F(a[i][j]) <= f)//最重要的事情最先做,如果路径满足矩阵且新点符合条件,更新子矩阵面积
sunmatrix = Math.max(sunmatrix, (maxi - mini + 1) * (maxj - minj + 1));//新子矩阵面积计算过程
int fxx = 0, fyy = 0;
int fx[] = {-1, 1, 0, 0};
int fy[] = {0, 0, -1, 1};//上下左右
for(int k = 0; k < 4; k ++) {
fxx = i + fx[k];
fyy = j + fy[k];
int bfmini = mini;
int bfmaxi = maxi;
int bfminj = minj;
int bfmaxj = maxj;
int bfminvalue = minvalue;
int bfmaxvalue = maxvalue;//存着用于回溯
if(ifmatrix()) {//是矩阵,扩张
if(fxx >= 0 && fxx < n && fyy >= 0 && fyy < m && visit[fxx][fyy] != true && F(a[fxx][fyy]) <= f) {
visit[fxx][fyy] = true;//标记来过
updatemx(fxx, fyy);//更新边界
dfs(a, fxx, fyy);
visit[fxx][fyy] = false;
}
}
else {//否者把目前范围矩阵遍历完
if(fxx >= mini && fxx <= maxi && fyy >= minj && fyy <= maxj && visit[fxx][fyy] != true && F(a[fxx][fyy]) <= f) {
visit[fxx][fyy] = true;
updatemx(fxx, fyy);
dfs(a, fxx, fyy);
visit[fxx][fyy] = false;
}
}
minvalue = bfminvalue;
maxvalue = bfmaxvalue;//回溯
mini = bfmini;
minj = bfminj;
maxi = bfmaxi;
maxj = bfmaxj;
}
}
public static boolean ifmatrix() {//判断此路径是否是矩阵
for(int i = mini; i <= maxi; i ++)
for(int j = minj; j <= maxj; j ++)
if(visit[i][j] != true) return false;
return true;
}
}
此代码虽然长,但只要弄懂上述问题,逐一解决,条理还是很清晰的,本代码在官方平台上测试能搞到九成分数,剩下的两个测试点是超时了。能对的都对了。想拿满分的话可以看看别的大佬写的别的方法,对于我来说如果真让我在赛场上遇到这道题的话,我能用这个朴素爆搜混点分就很满足的,打死也想不出其他方法了。

此代码能优化的我也优化了,如果有些地方还可以优化的话,欢迎各大佬指点。


我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度; 在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。
这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/
HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候
遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg
我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.
Java的Collections.unmodifiableList和Collections.unmodifiableMap在Ruby标准API中是否有等价物? 最佳答案 使用freeze应用程序接口(interface):Preventsfurthermodificationstoobj.ARuntimeErrorwillberaisedifmodificationisattempted.Thereisnowaytounfreezeafrozenobject.SeealsoObject#frozen?.Thismethodretur