UVAlive - 3029 City Game (图像)(扫描法)

https://vjudge.net/problem/UVALive-3029

题意:找出最大的子矩形。

只想到了纯暴力,复杂度太高了。

白书指导用扫描法,二维的扫描法,利用周围的元素维护当前元素,很微妙了。

从上到下设为垂线,up数组记录,如果是R,记为0,否则是同列上面元素+1。

从左到右利用lef数组维护,如果是R的话记得记为小于等于0的数,免得影响后续的判断,否则为max(同列上面元素,同行最左边的R即为lo+1),从右向左维护同理。

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;

int atlas[1005][1005],up[1005][1005],lef[1005][1005],ri[1005][1005];

int main()
{
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        int w,h;
        scanf("%d%d",&h,&w);
        for(int i=0;i<h;i++)
            for(int j=0;j<w;j++)
        {
            char t=getchar();
            while(t!='F'&&t!='R')t=getchar();
            if(t=='F')  atlas[i][j]=1;
            else atlas[i][j]=0;
        }
        int lo,ro;
        for(int i=0;i<h;i++)
        {
            lo=-1;
            for(int j=0;j<w;j++)
            {
                if(!atlas[i][j])
                {
                    up[i][j]=lef[i][j]=0;
                    lo=j;
                }
                else
                {
                    up[i][j]=i==0?1:up[i-1][j]+1;
                    lef[i][j]=i==0?lo+1:max(lef[i-1][j],lo+1);
                }
            }
        }



        int ans=0;
        for(int i=0;i<h;i++)
        {
            ro=w;
            for(int j=w-1;j>=0;j--)
            {
                if(!atlas[i][j])
                {
                    ro=j;
                    ri[i][j]=h+28;
                }
                else
                {
                    ri[i][j]=i==0?ro-1:min(ri[i-1][j],ro-1);
                    ans=max(ans,up[i][j]*(ri[i][j]-lef[i][j]+1));
                }
            }
        }

        printf("%d\n",ans*3);

    }
}

猜你喜欢

转载自blog.csdn.net/sadsummerholiday/article/details/82025126
今日推荐