zoukankan      html  css  js  c++  java
  • ZJOI2007 棋盘制作

    传送门

    DP找给定区域内最大符合条件的矩形/正方形。这里有一种新的方法———悬线法。

    悬线的定义:每个点(i,j),都对应一条悬线,当前点是悬线的下端,悬线的上端为一个障碍点或者矩形的上边界。

    所以一个符合条件的矩形,我们只要使用悬线法计算出这条悬线移动到不合法位置时的边界即可。

    (注意left和right似乎在iostream库中是保留字)

    用lef[i][j]表示从点(i,j)引出的悬线能拓展到的最左边的位置,righ[i][j]表示从点(i,j)引出的悬线能拓展到最右边的位置。up[i][j]表示这条悬线能向上拓展的最大长度。

    这样我们可以先预处理出每条悬线的lef,righ,只要左右两格不同就可以进行转移。

    之后我们就得到递推式:

    left[i][j]=max(left[i][j],left[i-1][j];
    right[i][j]=min(right[i][j],right[i-1][j];
    注意这里要考虑上一行的情况,是因为up的原因。
    之后从上向下DP,每次处理一下当前的最大合法矩形即可。
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    //#include<iostream>
    #include<cmath>
    #include<queue>
    #include<set>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    typedef long long ll;
    const int M = 50005;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
        if(ch == '-') op = -1;
        ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
        ans *= 10;
        ans += ch - '0';
        ch = getchar();
        }
        return ans * op;
    }
    
    int n,m,g[2005][2005],up[2005][2005],lef[2005][2005],right[2005][2005];
    int ans1,ans2;
    
    int main()
    {
        n = read(),m = read();
        rep(i,1,n)
        rep(j,1,m) g[i][j] = read(),lef[i][j] = right[i][j] = j,up[i][j] = 1;
        rep(i,1,n)
        rep(j,2,m) if(g[i][j] != g[i][j-1]) lef[i][j] = lef[i][j-1];
        rep(i,1,n)
        per(j,m-1,1) if(g[i][j] != g[i][j+1]) right[i][j] = right[i][j+1];
        rep(i,1,n)
        rep(j,1,m)
        {
        if(i > 1 && g[i][j] != g[i-1][j])
        {
            lef[i][j] = max(lef[i][j],lef[i-1][j]);
            right[i][j] = min(right[i][j],right[i-1][j]);
            up[i][j] = up[i-1][j]+1;
        }
        int lena = right[i][j] - lef[i][j] + 1;
        int lenb = min(lena,up[i][j]);
        ans1 = max(ans1,lenb*lenb);
        ans2 = max(ans2,lena*up[i][j]);
        }
        printf("%d
    %d
    ",ans1,ans2);
        return 0;
    }
     
  • 相关阅读:
    Oracle查询错误分析:ORA-01791:不是SELECTed表达式
    Java中DESKeySpec类
    linux发布项目
    mac下搭建cocos2d-x2.2.1版本android编译环境教程
    使用Eigen求解线性方程组
    视觉SLAM十四讲课后答案-ch1
    costmap_2d: obstacle_layer中关于激光雷达障碍物清除不干净的解决
    ch4 激光的前端配准算法一 —— ICP方法
    Project 'cv_bridge' specifies '/usr/include/opencv' as an include dir, which is not found.
    ch3 传感器数据处理II: 激光雷达运动畸变去除
  • 原文地址:https://www.cnblogs.com/captain1/p/9591973.html
Copyright © 2011-2022 走看看