计算几何 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;
}
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- C#递归算法之分而治之策略
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- C#算法之大牛生小牛的问题高效解决方法
- C#算法函数:获取一个字符串中的最大长度的数字
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- 经典排序算法之冒泡排序(Bubble sort)代码
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法