zoukankan      html  css  js  c++  java
  • 悬线法求最大子矩阵

    [戳我](https://www.luogu.com.cn/record/38515341)

    思路

    悬线法,顾名思义,就是我们从一个点开始,想左上方出两根线,构成一个矩阵,然后遍历所有的点,取一个最大值就可以了。所以我们之前可以预处理出一个点可以到达的最上面的点和最下面的点,然后枚举宽度,对宽度也就是行上面的点的l和r值取min就可以得到这个矩阵的长和宽了。顺便给出此题的单调栈做法,求取宽度的方法类似,只是枚举长度的时候用了一个单调栈去维护

    代码实现

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<iostream>
    #include<stack>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
    #define per(i,n,a) for (int i=n;i>=a;i--)
    #define MT(x,i) memset(x,i,sizeof(x) )
    #define rev(i,start,end) for (int i=start;i<end;i++)
    #define inf 0x3f3f3f3f
    #define mp(x,y) make_pair(x,y)
    #define lowbit(x) (x&-x)
    #define MOD 1000000007
    #define exp 1e-8
    #define N 1000005 
    #define fi first 
    #define se second
    #define pb push_back
    typedef long long ll;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    typedef vector <int> VI;
    typedef pair<int ,int> PII;
    typedef pair<int ,PII> PIII;
    ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
    void check_max (int &a,int b) { a=max (a,b);}
    void check_min (int &a,int b) { a=min (a,b);}
    inline int read() {
        char ch=getchar(); int x=0, f=1;
        while(ch<'0'||ch>'9') {
            if(ch=='-') f=-1;
            ch=getchar();
        } while('0'<=ch&&ch<='9') {
            x=x*10+ch-'0';
            ch=getchar();
        } return x*f;
    }
    const int maxn=3e3+10;
    int ans,n,m;
    int maze[maxn][maxn];
    int l[maxn][maxn],r[maxn][maxn];
    int up[maxn][maxn];
    inline int readc () {
        char c=getchar ();
        while (c!='R'&&c!='F') c=getchar ();
        if (c=='F') return 1;
        return 0;
    }
    
    int main () {
       scanf ("%d%d",&n,&m);
       ans=0;
       rep (i,1,n) 
        rep (j,1,m) maze[i][j]=readc (),up[i][j]=1,l[i][j]=r[i][j]=j;
       
       rep (i,1,n) 
        rep (j,2,m) if (maze[i][j]==1&&maze[i][j-1]==1) l[i][j]=l[i][j-1];
       rep (i,1,n) 
        per (j,m-1,1) if (maze[i][j]==1&&maze[i][j+1]==1) r[i][j]=r[i][j+1];
       
       rep (i,1,n) 
        rep (j,1,m) {
            if (i>1&&maze[i][j]==1&&maze[i-1][j]==1) {
                check_min (r[i][j],r[i-1][j]);
                check_max (l[i][j],l[i-1][j]);
                up[i][j]=up[i-1][j]+1;
            }
            check_max (ans,up[i][j]*(r[i][j]-l[i][j]+1));
        }
        printf ("%d
    ",3*ans);
        return 0;
    }
    
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
    #define per(i,n,a) for (int i=n;i>=a;i--)
    #define MT(x,i) memset(x,i,sizeof(x) )
    #define rev(i,start,end) for (int i=start;i<end;i++)
    #define inf 0x3f3f3f3f
    #define mp(x,y) make_pair(x,y)
    #define lowbit(x) (x&-x)
    #define MOD 1000000007
    #define exp 1e-8
    #define N 1000005 
    #define fi first 
    #define se second
    #define pb push_back
    typedef long long ll;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    typedef vector <int> VI;
    typedef pair<int ,int> PII;
    typedef pair<int ,PII> PIII;
    ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
    void check_max (int &a,int b) { a=max (a,b);}
    void check_min (int &a,int b) { a=min (a,b);}
    inline int read() {
        char ch=getchar(); int x=0, f=1;
        while(ch<'0'||ch>'9') {
            if(ch=='-') f=-1;
            ch=getchar();
        } while('0'<=ch&&ch<='9') {
            x=x*10+ch-'0';
            ch=getchar();
        } return x*f;
    }
    const int maxn=3e3+10;
    int t;
    struct node {
        int height,length;
    }st[maxn];
    int pos[maxn][maxn];
    int ans=0,temp=0;
    int n,m;
    
    inline int getc () {
        char c;
        c=getchar ();
        while (c!='R'&&c!='F') c=getchar ();
        if (c=='F') return 1;
        return 0;
    }
    
    void solve (int num) {
        int top=1,k;
        temp=0;
        st[1].height=pos[num][1];
        st[1].length=1;
        rep (i,2,m) {
            k=0;
            while (st[top].height>=pos[num][i]&&top>0) {
                k+=st[top].length;
                temp=max (temp,st[top--].height*k);
            }
            st[++top].height=pos[num][i];
            st[top].length=k+1;
        }
        k=0;
        while (top>0) {
            k+=st[top].length;
            temp=max (temp,st[top--].height*k);
        }
        ans=max (ans,temp);
    }
    
    int main () {
        MT (pos,0);
        scanf ("%d%d",&n,&m);
        rep (i,1,n) 
         rep (j,1,m) {
            int x=getc ();
            if (x==1) pos[i][j]=pos[i-1][j]+1;        
         }
        rep (i,1,n) solve (i);
        ans*=3;
        printf ("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    JS中的prototype与面向对象
    机电传动控制第二周学习笔记
    第三周作业
    机电传动控制第四周作业
    第五周学习笔记
    机电传动控制第一周学习笔记
    个人项目图书管理系统登陆功能模拟
    GITHUB使用及入门总结
    我的github地址
    工作压力改变了我?
  • 原文地址:https://www.cnblogs.com/hhlya/p/13687343.html
Copyright © 2011-2022 走看看