• 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;
    }
     
  • 相关阅读:
    跟面试官聊.NET垃圾收集,直刺面试官G点
    基于.net开发chrome核心浏览器【五】
    HTTP和HTTPS的区别(转)
    Java多线程
    Java常用设计模式
    MVC详解(转)
    java的反射机制浅谈(转)
    进程、线程与处理器的调度(转)
    请简单介绍一下什么是Spring?
    面向对象三大特性概述[封装、继承、多态](转)
  • 原文地址:https://www.cnblogs.com/captain1/p/9591973.html
Copyright © 2020-2023  润新知