面积
area.pas/c/cpp
问题描述:
给你一个长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
这一题由于矩形面积大,点较少,所以O(L*M)的悬线法就没法AC,只有80分
这里就要用到最大子矩形的O(n2)的算法,至于算法的实现,看看代码,分别按 x 和 y 排序,找两次
C++ Code
/*
C++ Code
http://blog.csdn.net/jiangzh7
*/
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 1010
#define max(a,b) (a)>(b)?(a):(b)
struct node{int x,y;};
int L,W,n;
node a[MAXN];
bool cmp1(node a,node b)
{
if(a.x==b.x)return a.y<b.y;
return a.x<b.x;
}
bool cmp2(node a,node b)
{
if(a.y==b.y)return a.x<b.x;
return a.y<b.y;
}
int main()
{
freopen("area.in","r",stdin);
freopen("area.out","w",stdout);
scanf("%d%d",&L,&W);//长 L 宽 W
scanf("%d",&n);
int i,j;
for(i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y);
a[++n].x=0;a[n].y=W;
a[++n].x=L;a[n].y=0;
sort(a+1,a+1+n,cmp1);
int best=0;
int high,low,maxx;
for(i=1;i<n;i++)
{
high=W,low=0;
for(j=i+1;j<=n;j++)
if(a[i].y>=low&&a[i].y<=high)
{
if(a[i].y==a[j].y)break;
best=max(best,(a[j].x-a[i].x)*(high-low));
if(a[j].y>a[i].y&&a[j].y<=high) high=a[j].y;
if(a[j].y<a[i].y&&a[j].y>=low) low=a[j].y;
}
}
sort(a+1,a+1+n,cmp2);
for(i=1;i<n;i++)
{
high=W,low=0;
for(j=i+1;j<=n;j++)
if(a[i].x>=low&&a[i].x<=high)
{
if(a[i].x==a[j].x)break;
best=max(best,(a[j].y-a[i].y)*(high-low));
if(a[j].x>a[i].x&&a[j].x<=high) high=a[j].x;
if(a[j].x<a[i].x&&a[j].x>=low) low=a[j].x;
}
}
printf("%d",best);
return 0;
}