zoukankan      html  css  js  c++  java
  • 【刷题】【垂线法】

    (luogu)

    悬线的定义是这样的:

    从每一个点向上走,知道遇到障碍点或顶边界。

    那么我们可以轻松地得到悬线的一些性质:

    1. 每一个点对应一根悬线
    2. 每一根悬线都对应了一个高度等于悬线高度,宽度大于0的矩形

    所以悬线法的步骤就是:找出每一个点对应的悬线的高度,然后向左右分别找出该悬线能拓展出的矩形的宽度。

    题面:

    小Q找到了一张由N×M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一。

    小Q想在这种纸中裁减一部分作为新棋盘,当然,他希望这个棋盘尽可能的大。

    当然,不管哪种,棋盘必须都黑白相间,即相邻的格子不同色,

    所以他希望可以找到最大的正方形棋盘面积和最大的矩形棋盘面积,从而决定哪个更好一些。

    棋盘制作

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    int n,m;
    const int N=2003;
    int d[N][N];
    int ll[N][N],rr[N][N],up[N][N];
    
    int main()
    {
        //输入 
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&d[i][j]),
                up[i][j]=1,ll[i][j]=rr[i][j]=j;
        //悬线法 
        
        for(int i=1;i<=n;i++)
            for(int j=2;j<=m;j++)
                if(d[i][j]^d[i][j-1]) 
                    ll[i][j]=ll[i][j-1];
        for(int i=1;i<=n;i++)
            for(int j=m-1;j;j--)
                if(d[i][j]^d[i][j+1]) 
                    rr[i][j]=rr[i][j+1];
        for(int j=1;j<=m;j++)
            for(int i=2;i<=n;i++)
                if(d[i][j]^d[i-1][j]) 
                    up[i][j]=up[i-1][j]+1,
                    ll[i][j]=max(ll[i][j],ll[i-1][j]),
                    rr[i][j]=min(rr[i][j],rr[i-1][j]);
        //统计答案 
        int s1=0,s2=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                int len=rr[i][j]-ll[i][j]+1;
                s1=max(s1,min(len,up[i][j]));
                s2=max(s2,len*up[i][j]);
            }
        printf("%d
    %d
    ",s1*s1,s2);
        return 0;
    }
    View Code
  • 相关阅读:
    java类型转换
    JVM内存各个区域分工简单介绍
    用数组实现栈
    一些关于Spring的随笔
    设计模式学习笔记(三)之静(动)态代理模式、适配器模式
    浅谈经典排序算法
    PetStore项目总结
    设计模式学习笔记(二)之观察者模式、装饰者模式
    Spring的校验(Validator)
    设计模式学习笔记(一)之工厂模式、单例模式
  • 原文地址:https://www.cnblogs.com/xwww666666/p/11729033.html
Copyright © 2011-2022 走看看