最大空凸包

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\n",ans);
}
posted @ 2021-09-08 21:08  LaiYiC  阅读(39)  评论(0编辑  收藏  举报