问题描述:
给你一个长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
悬线法死定了……
这里用一种稀疏点算法
很巧妙的办法
先分别对点进行x和y的排序
然后分别以x顺序和y顺序
枚举左右(下上)边界
这样矩形的一条边的长度已经算出来了
以枚举左右边界为例
另一条边的维护就是通过left 和 right
每次枚举到点j 如果j的横坐标小于i 那么更新left = max(left, Pnt[j].x)
否则是right
枚举上下同理
代码如下
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <algorithm>
using namespace std;
int L, W;
int N;
int ANS = -1;
struct E
{
int x;
int y;
}Pnt[2005];
int cmp1(E a, E b)
{
return a.x < b.x;
}
int cmp2(E a, E b)
{
return a.y < b.y;
}
void init_file()
{
freopen("area.in", "r", stdin);
freopen("area.out", "w", stdout);
}
void read_data()
{
scanf("%d%d%d", &L, &W, &N);
for(int i = 1; i <= N; i++)
{
scanf("%d%d", &Pnt[i].x, &Pnt[i].y);
}
Pnt[0].x = 0;
Pnt[0].y = 0;
N++;
Pnt[N].x = L;
Pnt[N].y = W;
}
void work()
{
sort(Pnt, Pnt + N, cmp2);
for(int i = 0; i < N; i++)
{
int _left = 0; int _right = L;
for(int j = i + 1; j <= N; j++)
{
ANS = max(ANS, (_right - _left) * (Pnt[j].y - Pnt[i].y));
if (Pnt[j].x > Pnt[i].x)
{
_right = min(Pnt[j].x, _right);
}
else _left = max(Pnt[j].x, _left);
}
}
sort(Pnt, Pnt + N, cmp1);
for(int i = 0; i < N; i++)
{
int _up = W; int _down = 0;
for(int j = i + 1; j <= N; j++)
{
ANS = max(ANS, (_up - _down) * (Pnt[j].x - Pnt[i].x));
if (Pnt[j].y > Pnt[i].y)
{
_up = min(_up, Pnt[j].y);
}
else _down = max(_down, Pnt[j].y);
}
}
printf("%d", ANS);
}
int main()
{
init_file();
read_data();
work();
return 0;
}