最大有效子矩阵

定义:

有效子矩阵:符合条件的子矩阵。

最大有效子矩阵:给定的矩阵中最大的有效子矩阵。

题目就是求最大有效子矩阵有多大?

能用DP写的前提是:最大有效子矩阵中每一个每一个矩阵都为有效矩阵.

见题:

题目显然求的是最大的有效子矩阵(正方形看做特殊的矩阵)。

这里就要讲到一个牛逼的方法,割线法。(我也是今天才学的).

记得以前学过确定最大有效正方形的大小的题,是用f[i][j]表示以点(i,j)最多向左和向右延展多长是有效的正方形。

状态转移:if(...)f[i][j]=min(f[i-1][j],min(f[i-1][j-1],f[j][i-1]))+1;

扫描二维码关注公众号,回复: 7087129 查看本文章

正方形用一个数组即表示信息,因为边长都相等.

但长方形就不行了,需要用三个数组,left[i][j],right[i][j],up[i][j];

分别表示以点(i,j)向左,向右,向上最大延展的长度.

先上代码:

#include<bits/stdc++.h>
const int maxn=2100;
using namespace std;
int n,m,ans1,ans2;
int l[maxn][maxn],r[maxn][maxn],u[maxn][maxn],a[maxn][maxn];
int main()
{
    freopen("1.in","r",stdin);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++) 
        {
            cin>>a[i][j];
            u[i][j]=l[i][j]=r[i][j]=1;//初始化每个点都不能延展,即长度都为1.
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(j==1) continue;
            if(a[i][j]!=a[i][j-1]) l[i][j]+=l[i][j-1];//预处理l数组,
        }
    for(int i=1;i<=n;i++)
        for(int j=m;j>=1;j--)
        {
            if(j==m) continue;
            if(a[i][j]!=a[i][j+1]) r[i][j]+=r[i][j+1];//预处理r数组.
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(i!=1&&a[i][j]!=a[i-1][j])
            {
                l[i][j]=min(l[i][j],l[i-1][j]);
                r[i][j]=min(r[i][j],r[i-1][j]);
                u[i][j]=u[i-1][j]+1;
            }
            int a=l[i][j]+r[i][j]-1;
            int b=u[i][j];
            ans1=max(min(a,b)*min(a,b),ans1);
            ans2=max(ans2,a*b);
        }    
    cout<<ans1<<endl<<ans2<<endl;
    return 0;
}

经过前两个预处理,每个点的l与r数组相加就会有一个长度,而一条枞线上的点就变成了长度不一的线段,那经过这条线的最大矩阵就是线的长度与最短长度的相乘.

我们可以看到在第三个f循坏里,还要更新l和r的信息,我们可以跟着走一遍会发现,这个循环的作用是寻找最短的长度,而抛弃原有的信息,我们可以发现l和r只随i的更新而更新.即随着i的更新,l和r不断寻找最短长度,而与左右的点得l和r的值无关.

 之后以此处理每个矩阵即可。

2:

#include<bits/stdc++.h>
const int maxn=1100;
using namespace std;
int n,m,l[maxn][maxn],r[maxn][maxn],u[maxn][maxn],ans;
char ch[maxn][maxn];
int main()
{
    freopen("1.in","r",stdin);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++) 
        {
            cin>>ch[i][j];
            if(ch[i][j]=='F') l[i][j]=r[i][j]=u[i][j]=1;
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(j==1) continue;
            if(ch[i][j]=='F') l[i][j]=l[i][j-1]+1;
        }
    for(int i=1;i<=n;i++)
        for(int j=m;j>=1;j--)
        {
            if(j==m) continue;
            if(ch[i][j]=='F') r[i][j]=r[i][j+1]+1;
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(ch[i][j]=='R') continue;
            if(i!=1&&ch[i-1][j]=='F')
            {
                l[i][j]=min(l[i][j],l[i-1][j]);
                r[i][j]=min(r[i][j],r[i-1][j]);
                u[i][j]=u[i-1][j]+1;
            }
            int a=l[i][j]+r[i][j]-1;
            int b=u[i][j];
            ans=max(ans,a*b);
        }
        cout<<ans*3<<endl;
        return 0;
} 

猜你喜欢

转载自www.cnblogs.com/gcfer/p/11404472.html
今日推荐