[单调栈] Jzoj P4260 最大子矩阵

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)
  • 用单调栈解决就好了

代码

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 using namespace std;
 5 int r,s,a[1010][1010],k[1010][1010],cnt,w[1010],ans;
 6 int main()
 7 {
 8     scanf("%d%d",&r,&s);
 9     for (int i=1;i<=r;i++)
10         for (int j=1;j<=s;j++)
11             scanf("%d",&a[i][j]),k[i][j]=1;
12     for (int j=2;j<=s;j++)
13         for (int i=2;i<=r;i++)
14             if (a[i][j]+a[i-1][j-1]<=a[i-1][j]+a[i][j-1]) k[i][j]=k[i-1][j]+1;
15     for (int i=1;i<=r;i++)
16         for (int j=1;j<=s;j++) 
17             if (k[i][j]==1) k[i][j]=0;
18     w[0]=1;
19     for (int i=2;i<=r;i++)
20     {
21         cnt=0;
22         for (int j=2;j<=s;j++)
23         {
24             while (cnt&&k[i][j]<=k[i][w[cnt]])
25             {
26                 ans=max(ans,k[i][w[cnt]]*(j-w[cnt-1]));
27                 cnt--;
28             }
29             w[++cnt]=j;
30         }
31         while (cnt)
32         {
33             ans=max(ans,k[i][w[cnt]]*(s+1-w[cnt-1]));
34             cnt--;
35         }
36     }
37     printf("%d",ans);
38     return 0;
39 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/9296250.html
今日推荐