全1第二大矩形

题意:给你一个只包含0和1的n×m大小的矩阵,问你第二大的全为1的矩形有多大。(不严格第二大)

题解:每个矩阵的大小由长和宽决定,矩形的长对应原矩阵中每一行最多有多少个元素,他们向上扩展的连续“1”的数量一样,矩形的宽对应向上扩展的连续“1”的数量。我们从第一行开始枚举,一开始先更新该行所有元素向上扩展最多有多少个连续“1”,设为c[j]数组,然后用一个单调递增的栈维护该行的c[j]数组,找出该行每个元素以自己为最小值,向左向右分别最远扩展到哪里,这里就有l[i],r[i]数组,此时最大的矩形面积应为(r[i]-l[i]+1)* c[j],第二小的值是max((r[i]-l[i])* c[j],(r[i]-l[i]+1) * (c[j] - 1)),然后不断更新最大值和第二大值,最后的第二大值就是答案。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
using namespace std;
const int maxn = 1005;
char a[maxn][maxn];
int c[maxn],l[maxn],r[maxn];
 
void update(int &mx,int &mmx,int x)
{
    if(x <= mmx)
        return;
    if(x <= mx)
    {
        mmx = x;
        return;
    }
    mmx = mx;
    mx = x;
}
 
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    int mx = 0,mmx = 0;
    for(int i=0; i<n; i++)
    {
        scanf("%s",a[i]);
    }
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<m; j++)
        {
            if(a[i][j] == '1')
                c[j]++;
            else
                c[j] = 0;
            l[j] = j;
            r[j] = m-1;
        }
        stack<int> s;
        for(int j=0; j<m; j++)
        {
            while(!s.empty() && c[j] <= c[s.top()])
            {
                l[j] = l[s.top()];
                r[s.top()] = j-1;
                s.pop();
            }
            s.push(j);
        }
        int mx1 = 0,mmx1 = 0;
        for(int j=0; j<m; j++)
        {
            int x = r[j] - l[j] + 1,y = c[j];
            update(mx1,mmx1,x*y);
            update(mx1,mmx1,(x-1)*y);
            update(mx1,mmx1,x*(y-1));
        }
        update(mx,mmx,mx1);
        update(mx,mmx,mmx1);
    }
    printf("%d",mmx);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值