zoukankan      html  css  js  c++  java
  • 悬线法 例题加解释 Luogu P1169 Luogu P4147

    悬线法用于求最大面积合法子矩阵。

    先上例题。

    Luogu P1169 棋盘制作:  https://www.luogu.org/problem/P1169

    这类的问题就是明显的悬线法。

    那么需要定义三个用于更新的数组。

    left[i][j]表示从(i,j)这个点出发向能到达最远的同行下标 

    right[i][j]表示从(i,j)这个点出发向能到达最远的同行下标

    up[i][j]表示从(i,j)这个点出发向能到达最远的距离

    那么我们就可以推出更新的方式。(伪代码)

    if(满足条件){
    
      right[i][j]=min(right[i][j],right[i-1][j]);
    
      left[i][j]=max(left[i][j],left[i-1][j]);
    
      up[i][j]=up[i-1][j]+1;
    
    }

    当然也需要预处理。

    首先处理所有点。

    for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                l[i][j]=r[i][j]=j,up[i][j]=1;

    然后需要处理出每一行的

    for(int i=1;i<=n;i++)
            for(int j=2;j<=m;j++)
                if(满足)
                    l[i][j]=l[i][j-1];
        for(int i=1;i<=n;i++)
            for(int j=m-1;j>=1;j--)
                if(满足)
                    r[i][j]=r[i][j+1];

    那么就可以更新矩阵的答案了。

    刚才例题代码如下。

    #include<bits/stdc++.h>
    #define sc(x) scanf("%d",&x)
    using namespace std;
    int n,m,ans1,ans2;
    int t[2001][2001];
    int l[2001][2001],r[2001][2001],u[2001][2001];
    int main()
    {
        sc(n),sc(m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                sc(t[i][j]),l[i][j]=r[i][j]=j,u[i][j]=1;
        for(int i=1;i<=n;i++)
            for(int j=2;j<=m;j++)
                if(t[i][j]!=t[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(t[i][j]!=t[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)
                    if(t[i][j]!=t[i-1][j]){
                        u[i][j]+=u[i-1][j];
                        l[i][j]=max(l[i][j],l[i-1][j]);
                        r[i][j]=min(r[i][j],r[i-1][j]);    
                    }
                int a=r[i][j]-l[i][j]+1;
                int b=min(a,u[i][j]);
                ans1=max(b*b,ans1);
                ans2=max(a*u[i][j],ans2);            
            }
        cout<<ans1<<endl<<ans2<<endl;
        return 0;
    }

    例题2

    Luogu P4147:https://www.luogu.org/problem/P4147

    也类似。用一种方式求解。

    #include<bits/stdc++.h>
    #define sc(x) scanf("%d",&x)
    using namespace std;
    int n,m,ans1,ans2;
    char t[2001][2001];
    int l[2001][2001],r[2001][2001],u[2001][2001];
    int main()
    {
        sc(n),sc(m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%s",&t[i][j]),l[i][j]=r[i][j]=j,u[i][j]=1;
        for(int i=1;i<=n;i++)
            for(int j=2;j<=m;j++)
                if(t[i][j]==t[i][j-1]&&t[i][j]=='F')
                    l[i][j]=l[i][j-1];
        for(int i=1;i<=n;i++)
            for(int j=m-1;j>=1;j--)
                if(t[i][j]==t[i][j+1]&&t[i][j]=='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)
                    if(t[i][j]==t[i-1][j]&&t[i][j]=='F'){
                        u[i][j]+=u[i-1][j];
                        l[i][j]=max(l[i][j],l[i-1][j]);
                        r[i][j]=min(r[i][j],r[i-1][j]);    
                    }
                int a=r[i][j]-l[i][j]+1;
                int b=min(a,u[i][j]);
                ans1=max(b*b,ans1);
                ans2=max(a*u[i][j],ans2);            
            }
        cout<<ans2*3<<endl;
        return 0;
    }
  • 相关阅读:
    java-Swatch的坑
    Java基本数据类型
    jQuery属性、事件、链式编程、$冲突
    jQuery页面改变大小事件,滑动页面事件
    JavaScript简介
    CSS页面布局格式
    CSS Float(浮动)
    css定位
    CSS知识点2
    CSS知识点1
  • 原文地址:https://www.cnblogs.com/ChrisKKK/p/11260741.html
Copyright © 2011-2022 走看看