2017icpc沈阳
http://acm.hdu.edu.cn/showproblem.php?pid=6219
const int N = 1e2+50;
int sgn(double x) { //判断x是否等于0
if(fabs(x) < eps) return 0;
else return x<0?-1:1;
}
struct Point {
double x,y;
Point() {}
Point(double x,double y):x(x),y(y) {}
Point operator + (Point B) {
return Point(x+B.x,y+B.y);
}
Point operator - (Point B) {
return Point(x-B.x,y-B.y);
}
Point operator / (double k) {
return Point(x/k,y/k);
}
double dis() {
return x*x+y*y;
}
};
struct Line {
Point p1,p2;
Line() {}
Line(Point p1,Point p2):p1(p1),p2(p2) {}
};
int n;
Point o;
int tot;
Point a[N],p[N];
double dp[N][N],ans;
//dp[i][j]表示组成的凸包以o,i,j为最后一个三角形的最大面积
typedef Point Vector;
double Cross(Vector A,Vector B) {
return A.x*B.y - A.y*B.x; //叉积
}
bool cmp(Point a,Point b) {
double res=Cross(a-o,b-o);
if(sgn(res)!=0)return res>0; //a在b的顺时针方向
return (a-o).dis() < (b-o).dis();
}
void solve() {
memset(dp,0,sizeof(dp));
sort(p+1,p+1+tot,cmp);
for(int i=1; i<=tot; i++) {
int j=i-1;
while(j&&!Cross(p[i]-o,p[j]-o))j--;
bool bz=(j==i-1);
while(j){
int k=j-1;
while(k&&Cross(p[i]-p[k],p[j]-p[k])>0)k--;
double area=fabs(Cross(p[i]-o,p[j]-o))/2;
if(k)area+=dp[j][k];
if(bz)dp[i][j]=area;
ans = max(ans,area);
j=k;
}
if(bz)for(int j=1;j<i;j++)dp[i][j]=max(dp[i][j],dp[i][j-1]);
}
}
void work() {
scanf("%d",&n);
ans =0;
for(int i=1; i<=n; i++) {
scanf("%lf%lf",&a[i].x,&a[i].y);
}
for(int i=1; i<=n; i++) { //选择凸包左下角的点
o=a[i];
tot=0;
for(int j=1; j<=n; j++) {
if(a[j].y>a[i].y || (a[i].y==a[j].y && a[j].x>a[i].x))p[++tot]=a[j];
}
solve();
}
printf("%.1f
",ans);
}