【最大子矩形】面积

来源:互联网 发布:大数据服务外包是什么 编辑:程序博客网 时间:2024/05/06 16:12

面积

问题描述:

给你一个长L,宽W的矩形纸,上面有n个黑点,你需要在这张纸上找出一个平行于坐标轴的最大矩形,使这个矩形中不包含黑点(可以在矩形边框上)。纸的一个顶点在(0,0),另一个顶点在(L,W)。

 

输入:

输入文件的第一行包含两个整数L和W,分别表示纸的长和宽。文件的第二行包含一个整数n,表示黑点的数量。以下n行每行包含两个整数x和y,表示一个黑点的坐标,可能重复。所有黑点都位于矩形纸内,即:0<=x<=L,0<=y<=W。 

 

输出:

输出文件仅一行,包含一个整数S,表示找到的矩形最大面积。

 

输入样例:

10 10

4

1 1

9 1

1 9

9 9

 

输出样例:

80

 

数据范围:

1<=L,W<=10000

对于50%的数据0<=n<=50

对于80%的数据0<=n<=200

对于100%的数据0<=n<=1000


拿到题我就以为是悬线法。但是因为可以把点放在边界上,因此左右界的更新先只用上一行的转移过来,修改完答案后,再根据这一行左右达到的最远处来转移。

而上界的转移也要单独处理,如果当前位置是障碍格,暂不修改它向上能够到达最远的位置。而到下一行时再修改。


实际上因为数据中的L、W都是极限数据,所以行不通。应该用时间复杂度和障碍点个数有关O(n^2)的算法。详细可以参见离散化的那一篇集训队论文。


简单来说,就是从一个点出发,向右移动,不断修改向上和向下能够到达的最大宽度,更新答案。注意还要从右到左,从上到下,从下到上再进行三次。

实际处理的时候要加上两个点,左上和右下,因为不一定要用障碍点来确定边界,而以矩形区域来确定。

要小心一种情况,即上下界或左右界被修正成一条线的情况。。


#include <cstdio>#include <string>#include <cstring>#include <algorithm>using std::sort;using std::min;using std::max;struct node{long x;long y;};node pos[1010];bool cmpr1(const node& n1,const node& n2){return n1.y < n2.y;}bool cmpr2(const node& n1,const node& n2){return n1.x < n2.x;}long getint(){long rs=0;bool sgn=1;char tmp;do tmp=getchar();while (!isdigit(tmp)&&tmp-'-');if (tmp=='-'){tmp=getchar();sgn=0;}do rs=(rs<<3)+(rs<<1)+tmp-'0';while (isdigit(tmp=getchar()));return sgn?rs:-rs;}int main(){freopen("area.in","r",stdin);freopen("area.out","w",stdout);long n = getint();long m = getint();long k = getint();long ans = 0;for (long i=1;i<k+1;i++){pos[i].x = getint();pos[i].y = getint();}k ++;pos[k].x = 0;pos[k].y = 0;k ++;pos[k].x = n;pos[k].y = m;sort(pos+1,pos+1+k,cmpr1);for (long i=1;i<k+1;i++){long top = 0;long bottom = n;for (long j=i+1;j<k+1;j++){ans = max(ans,(pos[j].y-pos[i].y)*(bottom-top));if (pos[j].y!=pos[i].y && pos[j].x <= pos[i].x)top = max(top,pos[j].x);if (pos[j].y!=pos[i].y && pos[j].x >= pos[i].x)bottom = min(bottom,pos[j].x);}}for (long i=k;i>0;i--){long top = 0;long bottom = n;for (long j=i-1;j>0;j--){ans = max(ans,(pos[i].y-pos[j].y)*(bottom-top));if (pos[j].y!=pos[i].y && pos[j].x <= pos[i].x)top = max(top,pos[j].x);if (pos[j].y!=pos[i].y && pos[j].x >= pos[i].x)bottom = min(bottom,pos[j].x);}}sort(pos+1,pos+1+k,cmpr2);for (long i=1;i<k+1;i++){long left = 0;long right = m;for (long j=i+1;j<k+1;j++){ans = max(ans,(pos[j].x-pos[i].x)*(right-left));if (pos[j].x!=pos[i].x && pos[j].y <= pos[i].y)left = max(left,pos[j].y);if (pos[j].x!=pos[i].x && pos[j].y >= pos[i].y)right = min(right,pos[j].y);}}for (long i=k;i>0;i--){long left = 0;long right = m;for (long j=i-1;j>0;j--){ans = max(ans,(pos[i].x-pos[j].x)*(right-left));if (pos[j].x!=pos[i].x && pos[j].y <= pos[i].y)left = max(left,pos[j].y);if (pos[j].x!=pos[i].x && pos[j].y >= pos[i].y)right = min(right,pos[j].y);}}printf("%ld",ans);return 0;}