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

题干:

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. 适量的注释有的时候真的让人看着神清气爽

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-23 14:22
点赞 评论 收藏
分享
机械打工仔:我来告诉你原因,是因为sobb有在线简历,有些HR为了快会直接先看在线简历,初步感觉不合适就不会找你要详细的了
投了多少份简历才上岸
点赞 评论 收藏
分享
07-22 11:12
门头沟学院 Java
不是,我就随手投的怎么还真发面试啊
皮格吉:大厂特别快的——来自已经被共享中
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务