hdu 6219 Empty Convex Polygons (凸包)
给你n个点,求面积最大的凸多边形,使得这个凸多边形没有内点。
考虑求凸包的graham算法,需要找到左下角的点,再进行极角排序后按顺序扫点,所以先枚举左下角的点。
这个过程中,如果遇到内点,就需要把这个内点排除掉,而现在需要把在外的点排除掉。
因为不确定凸包的边界,需要dp处理,一开始是一个三角线的两条边作为边界,然后不断枚举可能的边界进行扩展,同时保证不能包含内点。
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include <set> #include <queue> #define ll long long #define ld long double #define lson l,m,rt<<1 #define pi acos(-1) #define rson m+1,r,rt<<1|1 #define fo(i,l,r) for(int i = l;i <= r;i++) #define fd(i,l,r) for(int i = r;i >= l;i--) #define mem(x) memset(x,0,sizeof(x)) #define eps 3e-11 using namespace std; const int maxn = 55; const ll inf = 1e9; const ll mod = 998244353; ll read() { ll x=0,f=1; char ch=getchar(); while(!(ch>='0'&&ch<='9')) { if(ch=='-')f=-1; ch=getchar(); }; while(ch>='0'&&ch<='9') { x=x*10+(ch-'0'); ch=getchar(); }; return x*f; } int sgn(double x){ if(fabs(x)<eps)return 0; if(x<0)return -1; return 1; } struct Point{ int id; double x,y; Point(){ } Point(double _x,double _y){ x=_x; y=_y; } friend bool operator < (Point a,Point b) { return sgn(a.x-b.x)==0?sgn(a.y-b.y)<0:a.x<b.x; } double operator ^ (const Point &b) const{ return x*b.y - y*b.x; } bool operator == (const Point &b) const{ return sgn(x-b.x)==0&&sgn(y-b.y)==0; } Point operator - (const Point &b) const{ return Point(x-b.x,y-b.y); } double distance(Point b){ return sqrt((x-b.x)*(x-b.x) + (y-b.y)*(y-b.y)); } }; struct polygon{ int n; Point p[maxn]; struct cmp{ Point p; cmp(const Point &p0) {p=p0;} bool operator()(const Point &aa,const Point &bb){ Point a=aa,b=bb; int d=sgn((a-p)^(b-p)); if(d==0){ return sgn(a.distance(p) - b.distance(p)) < 0; } return d>0; } }; void norm(Point t){ sort(p+1,p+1+n,cmp(t)); } int relationpoint(Point q){ int cnt = 0; fo(i,0,n-1){ int j = (i+1)%n; int k = sgn((q-p[j])^(p[i]-p[j])); int u = sgn(p[i].y-q.y); int v = sgn(p[j].y-q.y); if(k>0&&u<0&&v>=0)cnt++; if(k<0&&v<0&&u>=0)cnt--; if(k==0)return 2; } return cnt != 0; } }ps,pts,rec; int n; bool ok[maxn][maxn][maxn]; double dp[maxn][maxn],ans; void gao(int st){ memset(dp,0,sizeof(dp)); int m = n-st+1; pts.n=m; fo(i,1,m){ pts.p[i] = ps.p[st+i-1]; } pts.norm(pts.p[1]); fo(i,2,m){ fo(j,i+1,m){ if(!ok[pts.p[1].id][pts.p[i].id][pts.p[j].id]){ dp[i][j] = 0; }else{ bool flag = true; fo(k,2,i-1){ if(sgn((pts.p[k]-pts.p[1])^(pts.p[i]-pts.p[1]))==0){ flag=false; break; } } if(flag)fo(k,2,i-1){ if(sgn((pts.p[i]-pts.p[k])^(pts.p[j]-pts.p[i]))>=0){ dp[i][j] = max(dp[i][j],dp[k][i]); } } dp[i][j] += ((pts.p[i]-pts.p[1]) ^ (pts.p[j]-pts.p[1]))/2.0; } ans=max(ans,dp[i][j]); } } } int main() { int T=read(); while(T--){ ans=0; n=ps.n=read(); fo(i,1,n){ ps.p[i] = Point(read(),read()); } sort(ps.p+1,ps.p+1+n); fo(i,1,n) ps.p[i].id=i; fo(i,1,n){ fo(j,i+1,n){ fo(k,j+1,n){ rec.n=3; rec.p[0]=ps.p[i];rec.p[1]=ps.p[j];rec.p[2]=ps.p[k]; ok[k][i][j]=ok[k][j][i]=ok[j][i][k]=ok[j][k][i]=ok[i][k][j]=ok[i][j][k]=true; if(sgn((rec.p[1]-rec.p[0])^(rec.p[2]-rec.p[0]))==0)continue; fo(t,1,n){ if(t==i||t==j||t==k)continue; if(rec.relationpoint(ps.p[t])==1){ ok[k][i][j]=ok[k][j][i]=ok[j][i][k]=ok[j][k][i]=ok[i][k][j]=ok[i][j][k]=false; break; } } } } } fo(i,1,n){ gao(i); } printf("%.1f\n",ans); } return 0; }