【NOIP2015模拟10.22】最大子矩阵

Description
我们将矩阵A中位于第i行第j列的元素记作A[i,j]。一个矩阵A是酷的仅当它满足下面的条件:
A[1,1]+A[r,s]<=A[1,s]+A[r,1] (r,s>1)
其中r为矩阵A的行数,s为矩阵A的列数。
进一步,如果一个矩阵是非常酷的仅当它的每一个至少包含两行两列子矩阵都是酷的。
你的任务是,求出一个矩阵A中的一个非常酷的子矩阵B,使得B包含最多元素。

Input
第一行包含两个整数R,S(2<=R,S<=1000),代表矩阵的行数与列数。
接下来R行每行包括S个整数,代表矩阵中的元素,矩阵中元素的绝对值不大于1000000。

Output
一行一个整数,代表子矩阵B的元素总数。如果没有一个非常酷的子矩阵,输出0。

Sample Input
输入1:
3 3
1 4 10
5 2 6
11 1 3
输入2:
3 3
1 3 1
2 1 2
1 1 1
输入3:
5 6
1 1 4 0 3 3
4 4 9 7 11 13
-3 -1 4 2 8 11
1 5 9 5 9 10
4 8 10 5 8 8

Sample Output
输出1:
9
输出2:
4
输出3:
15
【样例3解释】
在第三个样例中,子矩阵B的左上角为A[3,2],右下角为A[5,6]。

Data Constraint
对于60%的数据,满足R,S<=350。
对于100%的数据,满足2<=R,S<=1000,矩阵中元素的绝对值不大于1000000。
.
.
.
.
.

分析

一个矩阵为酷当且仅当它的每一个2*2的矩阵都是酷的
那么可以考虑求出每一个2*2的矩阵是否酷,把酷的矩阵染为颜色1,不酷的矩阵不染色
那么现在问题就转换为求一个含有最大面积的矩形(含1)
用单调栈做
.
.
.
.
.

程序:
#include<iostream>
using namespace std;
int b[1001][1001],a[1001][1001],c[1001],r,s,ans;
int main()
{
    cin>>r>>s;
    for (int i=1;i<=r;i++)
    for (int j=1;j<=s;j++)
    {
        cin>>a[i][j];
        b[i][j]=1;
    }
    for (int j=2;j<=s;j++)
    {
        for (int i=2;i<=r;i++)
        if (a[i-1][j-1]-a[i-1][j]<=a[i][j-1]-a[i][j]) b[i][j]=b[i-1][j]+1;
    }
    for (int i=1;i<=r;i++)
    for (int j=1;j<=s;j++)
    if (b[i][j]==1) b[i][j]=0;
    ans=0;
    c[0]=1;
    for (int i=2;i<=r;i++)
    {
        int h=0;
        for (int j=2;j<=s;j++)
        {
            while (h!=0&&b[i][j]<=b[i][c[h]])
            {
                int w=b[i][c[h]]*(j-c[h-1]);
                ans=max(ans,w);
                h--;
            }
            c[++h]=j;
        }
        while (h!=0)
        {
            int w=b[i][c[h]]*(s+1-c[h-1]);
            ans=max(ans,w);
            h--;
        }
    }
    cout<<ans;
}
原文地址:https://www.cnblogs.com/YYC-0304/p/9499930.html