• bzoj 1057 单调栈


    首先我们可以枚举每个一点,然后向下一直拓展到不能拓展为止,然后向下拓展的同时我们可以算出来向左最多拓展的个数,用单调栈来维护一个上升的序列,这样就类似与悬线法找最大01子矩阵了,但是对于这题01交替来说,好多细节比较麻烦,所以我们可以采用另一种转换方法,对于一个01矩阵来说,一定满足一下两个条件中的一个:

      1:矩阵中所有0的点(i,j),i与j的奇偶相同,且对于所有1点(i,j),i与j的奇偶不同。

      2:矩阵中所有0的点(i,j),i与j的奇偶不同,且对于所有1点(i,j),i与j的奇偶相同。

      那么我们把所有满足1条件的点标号为1,满足2条件的点标号为0,这样,我们就求出标号矩阵的01子矩阵就行了,还是使用单调栈的方法求,但是这里的最大0矩阵和最大1矩阵都有可能成为答案,所以我们先求最大1矩阵,然后将矩阵取非(!),在求一遍更新答案就好了。

      至于正方形和矩形的求法是相同的,只是更新答案的方式不同,特别的,最大子方阵也可以用DP来求解,设w[i][j]为以(i,j)点为右下角的方阵的最大边长(面积),转移为w[i][j]=min(w[i-1][j-1],w[i][j-1],w[i-1][j])+1。

      反思:没有考虑到DP的方阵局限性。

    /**************************************************************
        Problem: 1057
        User: BLADEVIL
        Language: C++
        Result: Accepted
        Time:2948 ms
        Memory:48168 kb
    ****************************************************************/
     
    //By BLADEVIL
    #include <cstdio>
    #include <algorithm>
    #define maxn 2010
    #define sqr(x) x*x
     
    using namespace std;
     
    int a[maxn][maxn],w[maxn],s[maxn],f[maxn][maxn],map[maxn][maxn];
    int top,n,m,ans1,ans2;
     
    void calc()
    {
        for (int j=1;j<=m;j++)
        {
            top=0;
            for (int i=1;i<=n;i++)
            {
                int minw=i;
                while (top&&s[top]>=f[i][j])
                {
                    ans1=max(ans1,s[top]*(i-w[top]));
                    ans2=max(ans2,sqr(min(s[top],i-w[top])));
                    minw=w[top--];
                }
                s[++top]=f[i][j]; w[top]=minw;
            }
        }
     
    }
     
    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]);
                if ((i&1)==(j&1)&&a[i][j]||(i&1)!=(j&1)&&!a[i][j]) map[i][j]=1; else map[i][j]=0;
            }
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
                if (map[i][j]) f[i][j]=f[i][j-1]+1; else f[i][j]=0;
        calc();
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
                map[i][j]=!map[i][j];
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
                if (map[i][j]) f[i][j]=f[i][j-1]+1; else f[i][j]=0;
        calc();
        printf("%d
    %d
    ",ans2,ans1);
        return 0;
    }
  • 相关阅读:
    An impassioned circulation of affection(尺取+预处理)
    旅游(CSUST省赛选拔赛2+状压dp+最短路)
    Islands and Bridges(POJ2288+状压dp+Hamilton 回路)
    Travelling(HDU3001+状压dp+三进制+最短路)
    Hie with the Pie(POJ3311+floyd+状压dp+TSP问题dp解法)
    hash(2018年CSUST省赛选拔赛第一场B题+hash+字典树)
    Everything Has Changed(HDU6354+圆交+求周长)
    [iOS Animation]-CALayer 图层几何学
    [iOS Animation]-CALayer 显示方式
    [iOS Animation]-CALayer 图层树
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3555834.html
Copyright © 2020-2023  润新知