您的位置:首页 > 其它

计算几何 BAPC 14 C itadel Construction (Gym 100526C )

2016-08-25 20:41 295 查看




题目意思是给定n各点,找四个点,使这四个点围成的面积最大。

首先用granham计算最大凸包,然后枚举最大的四边形,但是枚举的时候要注意优化。

可以这么考虑,若使四边形abcd面积最大,一定是ac最长的时候,再找最优的b跟d,凑成abcd。

#define SIZE 1001
struct point_t{
llt x,y;
}P[SIZE];

//叉积,OA×OB
inline llt cross(point_t const&O,point_t const&A,point_t const&B){
llt xoa = A.x - O.x;
llt yoa = A.y - O.y;
llt xob = B.x - O.x;
llt yob = B.y - O.y;
return xoa * yob - xob * yoa;
}

//A如果比B更靠下更靠左返回真
inline bool isLowLeft(point_t const&A,point_t const&B){
return A.y < B.y || ( A.y == B.y && A.x < B.x );
}

//按照对于pO的极角排序,极角相等的距离远的排在前面,因为后面要做一个unique
point_t* pO;
bool comp4Graham(point_t const&A,point_t const&B){
llt t = cross(*pO,A,B);
if ( t ) return t > 0LL;

llt a1 = A.x > pO->x ? A.x - pO->x : pO->x - A.x;
llt a2 = B.x > pO->x ? B.x - pO->x : pO->x - B.x;
if ( a1 != a2 ) return a1 > a2;

a1 = A.y > pO->y ? A.y - pO->y : pO->y - A.y;
a2 = B.y > pO->y ? B.y - pO->y : pO->y - B.y;
return a1 > a2;
}

//相对于pO是否极角相等
inline bool isEqPolar(point_t const&A,point_t const&B){
return 0LL == cross(*pO,A,B);
}

//Graham求凸包,结果当中没有共线点,起点总是最下最左点
int Graham(point_t P[],int n){
if ( 1 == n ) return 1;

//寻找最下最左点
point_t *p = min_element(P,P+n,isLowLeft);

//交换
swap(*p,P[0]);

if ( 2 == n ) return 2;

//按极角排序,极角相等,距离近的排在前面
pO = P;
sort(P+1,P+n,comp4Graham);

//将相对于pO的共线点均剔除,只保留最后一个
p = unique(P+1,P+n,isEqPolar);
n = p - P;

//真正的Graham循环
int top = 2;
for(int i=2;i<n;++i){
while( top > 1 && cross(P[top-2],P[top-1],P[i]) <= 0LL )
--top;
P[top++] = P[i];
}
return top;
}

int area2( point_t const&p1,point_t const&p2,point_t const&p3){
return abs( p2.x*p3.y - p2.x*p1.y - p1.x*p3.y + p1.x*p1.y - p2.y*p3.x + p2.y*p1.x + p1.y*p3.x - p1.y*p1.x );
}

int main(){
int t;scanf("%d",&t);
while(t--){
int n;scanf("%d",&n);
for(int i=0;i<n;++i)scanf("%d%d",&P[i].x,&P[i].y);
n = Graham(P,n);

int a,b,c,d;
int ans = -1;
for( a = 0;a < n; ++a){
b = a;
d = a+1;
for ( c = a+1; c < n;++c ) {
while( b < c && area2(P[a],P[b+1],P[c]) >= area2(P[a],P[b],P[c]) )
b++;
//while( d < c) d++;
while( d < n-1 && area2(P[a],P[c],P[d+1]) >= area2(P[a],P[c],P[d]) )
d++;
ans = max(ans, area2(P[a],P[b],P[c]) + area2(P[a],P[c],P[d]) );
}
}
if ( ans % 2 ){
printf("%d.5\n",ans/2);
}else printf("%d\n",ans/2);

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