操练

69 篇文章 0 订阅

操练


问题描述

高老大有一个 NN 的广场,被均分成 NN 个格子。
其中某些格子种上了树。
为了维护世界的和平,为了贯彻和平与发展的原则,老大不得不开始操练部下了。
部下们必须站在广场中某没种上树个格子中,而且一个格子内不允许有两个人站着。
同时,为了显得整齐划一,部下们要维护一个方阵的阵型,也就是 NN 的广场内的一个 XY 的矩形(该矩形的长和宽必须与广场的长和宽平行),每个格子上都必须有一个部下。
现在老大想知道,一次最多操练多少个部下?


输入

输入文件名为Training.in。
输入第一行两个正整数 N M,代表广场的长和宽。
下接一个 N M 列的字符矩阵,若第 I 行第 J 列为‘0’则代表该格子上有一颗树。


输出

输出文件名为Training.out。
输出一次最多能够操练的部下个数。


输入样例

2
11
11


输出样例

4


数据范围

对于 80% 的数据, N<=250
对于 100% 的数据, N<=1000


Solution

悬线法


Code

#include <iostream>
#include <cstdio>

#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y)) 

using namespace std;

int n,ans;

int map[1010][1010];
int up[1010][1010];
int le[1010][1010];
int ri[1010][1010];

int main(){

    freopen("training.in","r",stdin);
    freopen("training.out","w",stdout);

    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%1d",&map[i][j]);
    for(int i=1;i<=n;i++)ri[0][i]=n,le[0][i]=1;
    for(int i=1;i<=n;i++){
        int t=1;
        for(int j=1;j<=n;j++){
            if(map[i][j])le[i][j]=t;
            else le[i][j]=1,t=j+1;
        }
        t=n;
        for(int j=n;j>=1;j--){
            if(map[i][j])ri[i][j]=t;
            else ri[i][j]=n,t=j-1;
        }
        for(int j=1;j<=n;j++)if(map[i][j]){
            up[i][j]=up[i-1][j]+1;
            le[i][j]=Max(le[i][j],le[i-1][j]);
            ri[i][j]=Min(ri[i][j],ri[i-1][j]);
            ans=Max(ans,(ri[i][j]-le[i][j]+1)*up[i][j]);
        }
    }
    printf("%d\n",ans);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值