0
点赞
收藏
分享

微信扫一扫

【POJ - 3494】Largest Submatrix of All 1’s(加一点思维后化成 单调栈)

看山远兮 2022-06-15 阅读 9

题干:

Given a m-by-n (0,1)-matrix, of all its submatrices of all 1’s which is the largest? By largest we mean that the submatrix has the most elements.

Input

The input contains multiple test cases. Each test case begins with m and n (1 ≤ mn ≤ 2000) on line. Then come the elements of a (0,1)-matrix in row-major order on m lines each with n numbers. The input ends once EOF is met.

Output

For each test case, output one line containing the number of elements of the largest submatrix of all 1’s. If the given matrix is of all 0’s, output 0.

Sample Input

2 2
0 0
0 0
4 4
0 0 0 0
0 1 1 0
0 1 1 0
0 0 0 0

Sample Output

0
4

题目大意:

        求最大的子矩阵中数的和(其实也就是1的个数)

解题报告:

大佬说:   想起在学习dp时,曾经遇到过矩形求最大n子段和问题,用的状态压缩,这里也可以用这个,把矩形压缩成一条线,然后的过程,就是例题求矩形面积了,不过这里要求n遍,因为每行都要压缩,每行都要求一遍。于是这个题变得就简单多了。不过要注意的是最后需要枚举每一行的状态,而不能枚举maze值最大那一行的状态,(即:就算这一行的某一列是把这一列本该有的那个高度拦腰折断,也要枚举这一行)因为说不定在别的列的值大呢,而且,就算拦腰折断了,这也算是一种状态啊,所包含的所有状态必须全部枚举一遍,不重不漏,才能保证最终结果的正确性。

AC代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<stack>

using namespace std;
const int MAX = 2000 + 5;
int n,m;
int maze[MAX][MAX];
int L[MAX],R[MAX];

void getl(int i) {
stack<int > sk;
//要找他左侧的第一个严格比他小的元素 所以需要从左向右维护一个严格单调递增栈
for(int j = 1; j<=n; j++) {
while(!sk.empty() && maze[i][sk.top() ]>=maze[i][j] ) sk.pop();
if(sk.empty() ) L[j] = 0;
else L[j] = sk.top();
sk.push(j);
}

}
void getr(int i) {
stack<int > sk;
//要找他右侧的第一个严格比他小的元素 所以需要从右向左维护一个严格单调递增栈
for(int j = n; j>=1; j--) {
while(!sk.empty() && maze[i][sk.top() ]>=maze[i][j] ) sk.pop();
if(sk.empty() ) R[j] = n+1;
else R[j] = sk.top();
sk.push(j);
}

}
void init() {
for(int i = 1; i<=m; i++)
for(int j = 1; j<=n; j++)
maze[i][j]=0;
}
int main()
{
while(~scanf("%d %d",&m,&n) ) {//m行n列
init();
for(int i = 1; i<=m; i++) {
for(int j = 1; j<=n; j++) {
int tmp;
scanf("%d",&tmp);
if(tmp==1) {
maze[i][j]=maze[i-1][j]+1;
}
}
}
//至此我们已经有了截止第i行的(1~i)每一个j的连续高度,

int maxx=-1;
for(int i = 1; i<=m; i++) {
getl(i);
getr(i);
//加入实时判断,这样就不用开二维的L[][]和R[][]了!!
// printf("i=%d 时 ",i);
for(int j = 1; j<=n; j++) {
// printf("L[%d] =%d ",j,L[j]);
maxx= max(maxx, maze[i][j] * (R[j] - L[j] -1) );
}
// printf("\n");
}
printf("%d\n",maxx);
}

return 0 ;
}

总结:  

   1.实时判断!这样就不用开一个二维数组了!最近很多题都用到了for循环中实时判断实时操作的题!以后有空来一波总结。

   2. 适量的注释有的时候真的让人看着神清气爽


举报

相关推荐

0 条评论