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;
    }
     
  • 相关阅读:
    事务传播机制,搞懂。
    洛谷 P1553 数字反转(升级版) 题解
    洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is Here 题解
    洛谷 P1055 ISBN号码 题解
    洛谷 P2141 珠心算测验 题解
    洛谷 P1047 校门外的树 题解
    洛谷 P1980 计数问题 题解
    洛谷 P1008 三连击 题解
    HDU 1013 题解
    HDU 1012 题解
  • 原文地址:https://www.cnblogs.com/captain1/p/9591973.html
Copyright © 2011-2022 走看看