您的位置:首页 > 其它

操练

2016-07-05 17:22 387 查看

问题描述 Problem Description

高老大有一个 N∗N 的广场,被均分成 N∗N 个格子。其中某些格子种上了树。

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

输入描述 Input Description

输入第一行两个正整数 N 和 M ,代表广场的长和宽。

接一个 N 行 M 列的字符矩阵,若第 I 行第 J 列为 0 则代表该格子上有一颗树。

输出描述 Output Description

输出一次最多能够操练的部下个数。

输入样例 Sample Input

2

11

11

输出样例 Sample Output

4

数据范围及提示 Data Size & Hint

对于 80% 的数据, N≤250;

对于 100% 的数据, N≤1000 。

分析 I Think

记 si,j 表示在 (i,j) 的上面(含)有连续多少个 1 ,若 ai,j=0,则 si,j=0 ,然后枚举每一行的 si ,再用一个单调队列来维护,要求队列中的每一个元素都比前面的元素大,他们的入队时间,记列的编号,每当有元素弹出时就更新 ans。

代码 Code

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int Size = 1010;

int a[Size][Size];
int up[Size][Size];
int stack[Size],top;
int time[Size];
int n;

int main(){

scanf("%d",&n);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j){
scanf("%1d",&a[i][j]);
if(a[i][j])
up[i][j] = up[i-1][j]+1;
}
for(int i=1;i<=n;++i)
up[i][n+1] = -1;

int ans = 0;
for(int i=1;i<=n;++i){
stack[top=0] = -1;
for(int j=1;j<=n+1;++j)
if(up[i][j] > stack[top]){
stack[++top] = up[i][j];
time[top] = j;
}
else{
while(top && up[i][j]<stack[top]){
ans = max(ans,stack[top]*(j-time[top]));
--top;
}
if(stack[top] != up[i][j])
stack[++top] = up[i][j];
}
}

printf("%d",ans);

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: