• 悬线法学习笔记


    悬线法:一般求最大子矩形

    悬线法,悬线的定义,就是一条竖线,这条竖线要满足上端点在整个矩形上边界或者是一个障碍点。然后以这条悬线进行左右移动,直到移至障碍点或者是矩阵边界,进而确定这条悬线所在的极大矩阵。

    所以我们需要(Left[])数组存每个点能到达的最右位置,(Right[])数组存放每个点能到达的最左位置,(Up[])数组位置。

    设置好这些数组之后,我们开始遍历矩阵中的每个点,把每个点和上一个点的(Left)(Right)进行比较,分别取最大和最小,Up则是上一个点的Up+1,进而求出面积进行比较。

    经典例题:
    ZJOI2007 棋盘制作

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define MAXN 2010
    using namespace std;
    int l[MAXN][MAXN],r[MAXN][MAXN],up[MAXN][MAXN],a[MAXN][MAXN];
    int n,m,ans1,ans2;
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&a[i][j]),l[i][j]=j,r[i][j]=j,up[i][j]=1;
        for(int i=1;i<=n;i++)
            for(int j=2;j<=m;j++)
                if(a[i][j]==1-a[i][j-1])
                    l[i][j]=l[i][j-1];
        for(int i=1;i<=n;i++)
            for(int j=m-1;j>=1;j--)
                if(a[i][j]==1-a[i][j+1])
                    r[i][j]=r[i][j+1];
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(i>1&&a[i][j]==1-a[i-1][j])
                {
                    up[i][j]=up[i-1][j]+1;
                    l[i][j]=max(l[i-1][j],l[i][j]);
                    r[i][j]=min(r[i-1][j],r[i][j]);
                }
                int kuan=r[i][j]-l[i][j]+1;
                int square=min(kuan,up[i][j]);
                ans1=max(ans1,square*square);
                ans2=max(ans2,kuan*up[i][j]);
            }
        }
        printf("%d
    %d
    ",ans1,ans2);
        return 0;
    } 
    

    luogu 玉蟾宫

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define MAXN 2010
    using namespace std;
    int l[MAXN][MAXN],r[MAXN][MAXN],up[MAXN][MAXN];
    char a[MAXN][MAXN];
    int n,m,ans1,ans2;
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                cin>>a[i][j],l[i][j]=j,r[i][j]=j,up[i][j]=1;
        for(int i=1;i<=n;i++)
            for(int j=2;j<=m;j++)
                if(a[i][j]=='F'&&a[i][j-1]=='F')
                    l[i][j]=l[i][j-1];
        for(int i=1;i<=n;i++)
            for(int j=m-1;j>=1;j--)
                if(a[i][j]=='F'&&a[i][j+1]=='F')
                    r[i][j]=r[i][j+1];
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(i>1&&a[i][j]=='F'&&a[i-1][j]=='F')
                {
                    up[i][j]=up[i-1][j]+1;
                    l[i][j]=max(l[i-1][j],l[i][j]);
                    r[i][j]=min(r[i-1][j],r[i][j]);
                }
                int kuan=r[i][j]-l[i][j]+1;
                ans2=max(ans2,kuan*up[i][j]);
            }
        }
        printf("%d
    ",3*ans2);
        return 0;
    } 
    
  • 相关阅读:
    C# 对串口的操作
    【STM32】手册理解
    【LCD MENU】710
    【交流采集——RMS(均方根)】电压和电流
    【DMA】配置及使用
    【ADC】ADC初始化的注意事项
    【电源】开关型功率变换器的基本结构
    【单片机】【710】逆变
    【单片机】【710】PWM
    【单片机】【710】振荡器和系统时钟
  • 原文地址:https://www.cnblogs.com/fengxunling/p/9935945.html
Copyright © 2020-2023  润新知