题意:给定N个点,选出其中8个点组成两个矩形,使得两个矩形的面积和最大。
限制条件:
1、一定得构成两个矩形
2、两个矩形不能有交叉,不能共用顶点,边不能有部分重合。
如果不能满足条件,输出imp。
现场赛的时候这题坑了不少人,我那会是看着很多人没过才细想,要不然,估计我也得WA。
这题由于N才30,所以可以枚举了事。
但是有一个坑点,就是虽然矩形相交不可以,但是可以嵌套,如果一个大矩形套一个小矩形,面积只能算大的。因为题目的实际背景是求两个矩形围起来的地的总面积。
我的做法可能麻烦了些,不想看超长代码的请绕道。。。
虽说我现场赛就是这么写的,,,写的快晕,幸好只是因为freopen的问题2Y。
对于N<8的情形是直接输出imp,因为根本没法构成两个矩形。
先将点按照X坐标大小排序。
记找到的第一个矩形是A,第二个是B。
然后枚举左下角的顶点,然后找到跟它相同X坐标以及Y坐标的顶点,作为左上角和右下角。看看能不能找到右上角,找到了作为第一组点。
接着枚举第二个矩形的左下角。如果是刚好在某条A的边上,排除。
第一个确定了,枚举后面三个点的方法同上。
注意,如果第一个点是在A内的,后面三个点也要。如果满足了,那么此时的面积是A的面积。
如果第一个点在A外面,那么后三个点也是在A外面。
枚举得到A和B了,虽然保证B不在A里面,但是有可能A和B交叉,判断方法是统计A的顶点有多少个在B里面。
如果有4个,说明B包含了A,面积是A的面积。
如果没有,说明A和B独立,把A和B的面积加起来。
剩下说明有交叉,忽略。
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
const int N = 30;
const int M = 210;
map<int, map<int,int> > MP;
vector<int> X[M], Y[M];
typedef vector<int>::iterator vit;
#define all(it, V) for(vit it=V.begin(); it!=V.end(); it++)
struct Point{
int x, y;
bool operator < (const Point &A)const{
return x<A.x || (x==A.x && y<A.y);
}
}p[N];
int n, ans, a[4], b[4];
bool flag[N];
bool on_seg(int *arr, int i){
if(p[arr[0]].x==p[i].x){
return p[arr[0]].y<=p[i].y && p[i].y<=p[arr[1]].y;
}
if(p[arr[2]].x==p[i].x){
return p[arr[2]].y<=p[i].y && p[i].y<=p[arr[3]].y;
}
if(p[arr[0]].y==p[i].y){
return p[arr[0]].x<=p[i].x && p[i].x<=p[arr[2]].x;
}
if(p[arr[1]].y==p[i].y){
return p[arr[1]].x<=p[i].x && p[i].x<=p[arr[3]].x;
}
return 0;
}
bool in(int *arr, int i){
return (p[arr[0]].x<p[i].x && p[i].x<p[arr[2]].x) && (p[arr[0]].y<p[i].y && p[i].y<p[arr[1]].y);
}
bool in2(int *arr, int i){
return (p[arr[0]].x<=p[i].x && p[i].x<=p[arr[2]].x) && (p[arr[0]].y<=p[i].y && p[i].y<=p[arr[1]].y);
}
int area(int *arr){
return (p[arr[2]].x-p[arr[0]].x) * (p[arr[1]].y-p[arr[0]].y);
}
void solve1(){
all(i, X[p[b[0]].x]){
if(p[*i].y<=p[b[0]].y || flag[*i]) continue;
if(!in(a, *i)) continue;
b[1] = *i;
all(j, Y[p[b[0]].y]){
if(p[*j].x<=p[b[0]].x || flag[*j]) continue;
if(!in(a, *j)) continue;
b[2] = *i;
if(MP[p[b[2]].x].count(p[b[1]].y)){
b[3] = MP[p[b[2]].x][p[b[1]].y];
if(!flag[b[3]])
ans = max(ans, area(a));
}
}
}
}
void cal(){
int cnt = 0;
for(int i=0; i<4; i++){
if(in(b, a[i])) cnt++;
if(on_seg(b, a[i])) return;
}
if(cnt == 0) ans = max(ans, area(a)+area(b));
else if(cnt == 4) ans = max(ans, area(b));
}
void solve2(){
all(i, X[p[b[0]].x]){
if(p[*i].y<=p[b[0]].y || flag[*i]) continue;
if(in2(a, *i)) continue;
b[1] = *i;
all(j, Y[p[b[0]].y]){
if(p[*j].x<=p[b[0]].x || flag[*j]) continue;
if(in2(a, *j)) continue;
b[2] = *j;
if(MP[p[b[2]].x].count(p[b[1]].y)){
b[3] = MP[p[b[2]].x][p[b[1]].y];
if(!in2(a, b[3]) && !flag[b[3]]){
cal();
}
}
}
}
}
void solve(){
memset(flag, 0, sizeof(flag));
for(int i=0; i<4; i++) flag[a[i]] = 1;
for(int i=0; i<n; i++){
if(flag[i]) continue;
if(on_seg(a, i)) continue;
b[0] = i;
if(in(a, i)) solve1();
else solve2();
}
}
int main(){
while(~scanf("%d", &n) && n){
for(int i=0; i<n; i++){
scanf("%d %d", &p[i].x, &p[i].y);
X[p[i].x].clear();
Y[p[i].y].clear();
}
if(n<8){
puts("imp");
continue;
}
sort(p, p+n);
MP.clear();
for(int i=0; i<n; i++){
MP[p[i].x][p[i].y] = i;
X[p[i].x].push_back(i);
Y[p[i].y].push_back(i);
}
ans = -1;
for(int i=0; i<n; i++){
a[0] = i;
all(j, X[p[a[0]].x]){
if(p[*j].y <= p[a[0]].y) continue;
a[1] = *j;
all(k, Y[p[a[0]].y]){
if(p[*k].x <= p[a[0]].x) continue;
a[2] = *k;
if(MP[p[a[2]].x].count(p[a[1]].y)){
a[3] = MP[p[a[2]].x][p[a[1]].y];
solve();
}
}
}
}
if(ans==-1) puts("imp");
else printf("%d\n", ans);
}
return 0;
}