zoukankan      html  css  js  c++  java
  • 悬线法学习笔记

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

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

    所以我们需要(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;
    } 
    
  • 相关阅读:
    setContentView和inflate区别
    Android之用HTTP的get,post,HttpClient三种方式向service提交文本数据
    用C#製作PDF文件全攻略
    移动平台前端开发总结(针对iphone,Android等手机)
    Android实现左右滑动指引效果
    为 iPhone 和 iPad 自定义网站的主屏幕图标
    android 布局中的单位及分辨率自解
    纯css页面变灰度兼容ie、firefox、chrome、opera、safari
    Android判断网络连接是否可用(代码)
    Android实现渐显按钮的左右滑动效果
  • 原文地址:https://www.cnblogs.com/fengxunling/p/9935945.html
Copyright © 2011-2022 走看看