51nod 1158:全是1的最大子矩阵

基准时间限制:1 秒 空间限制:131072 KB 分值: 80  难度:5级算法题
 收藏
 关注
给出1个M*N的矩阵M1,里面的元素只有0或1,找出M1的一个子矩阵M2,M2中的元素只有1,并且M2的面积是最大的。输出M2的面积。
Input
第1行:2个数m,n中间用空格分隔(2 <= m,n <= 500)
第2 - N + 1行:每行m个数,中间用空格分隔,均为0或1。
Output
输出最大全是1的子矩阵的面积。
Input示例
3 3
1 1 0
1 1 1
0 1 1
Output示例
4

求出每行每个位置的能连续1的最大值。例子中的矩阵变为:

1 2 0 

1 2 3

0 1 2

然后发现对于每一列来说,要求的是一个区间内的最小值乘以区间长度,所有这些值的最大值。这就是对一个元素的两边进行扩展,发现这就是单调栈的应用了。

代码:

#pragma warning(disable:4996)  
#include <iostream>  
#include <algorithm>  
#include <cmath>  
#include <vector>  
#include <string>  
#include <cstring>  
using namespace std;

int res;
int m, n;

int lef[505], sta[505];
int row[505][505];
int val[505][505];

void input()
{
	int i, j;
	
	res = 0;
	scanf("%d%d", &m, &n);

	for (i = 1; i <= m; i++)
	{
		for (j = 1; j <= n; j++)
		{
			scanf("%d", &val[i][j]);
			if (val[i][j])
			{
				val[i][j] = val[i][j - 1] + 1;
				res = max(res, val[i][j]);
			}
		}
	}
}

void solve()
{
	int i, j, k;

	res = 0;
	for (j = 1; j <= n; j++)
	{
		int top = 0;
		val[m + 1][j] = -1;
		for (i = 1; i <= m + 1; i++)
		{
			if (top == 0 || val[i][j] > val[sta[top - 1]][j])
			{
				sta[top++] = i;
				lef[i] = i;
				continue;
			}
			if (val[i][j] == val[sta[top - 1]][j])
			{
				continue;
			}
			while (top >= 1 && val[i][j] < val[sta[top - 1]][j])
			{
				--top;
				int tmp = (i - lef[sta[top]])*val[sta[top]][j];
				res = max(res, tmp);
			}
			lef[i] = lef[sta[top]];
			sta[top++] = i;
		}
	}
	cout << res << endl;
}

int main()
{
	//freopen("i.txt", "r", stdin);
	//freopen("o.txt", "w", stdout);

	input();
	solve();

	//system("pause");
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值