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;
    }
     
  • 相关阅读:
    com.panie 项目开发随笔_前后端框架考虑(2016.12.8)
    Jsoup 使用教程:数据抽取
    Jsoup 使用教程:输入
    项目中图片处理总结
    jsonp 跨域请求
    由Memcached升级到 Couchbase的 Java 客户端的过程记录(三)
    由Memcached升级到 Couchbase的 Java 客户端的过程记录(二)
    jquery eval解析JSON中的注意点介绍
    JS禁止WEB页面鼠标事件大全
    jQuery事件之鼠标事件
  • 原文地址:https://www.cnblogs.com/captain1/p/9591973.html
Copyright © 2011-2022 走看看