A Classic Myth: Flatland Superhero
http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11264&courseid=107
题意:在二维平面内给若干点,现在在用一个平行四边形把所有的点都围住,求满足这个条件的最小平行四边形面积。
思路:
把凸包弄出来后,直接枚举凸包上的两条边,作为平行四边形的相邻边,再求出到这两边最远的两个点,来生成另外两条边。
然后知道四条边,可以求出四个顶点,再求面积就好了。

#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<iostream> using namespace std; struct point{ double x,y; void scan(){scanf("%lf %lf",&x,&y);} friend bool operator < (const point &l,const point &r){ return l.y < r.y || (l.y==r.y&&l.x<r.x); } }as[1005],bs[1005]; int dis[1005]; double xmult(double x1,double y1,double x2,double y2,double x0,double y0){ return (x1-x0)*(y2-y0)-(x2-x0)*(y1-y0); } double distance(double x1,double y1,double x2,double y2){ return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } //点到直线的距离 double disptoline(double x,double y,double x1,double y1,double x2,double y2){ return fabs(xmult(x,y,x1,y1,x2,y2))/distance(x1,y1,x2,y2); } bool mult(point sp,point ep,point op){ return (sp.x - op.x) * (ep.y - op.y) >= (ep.x - op.x) * (sp.y - op.y); } //求凸包 int graham(point pnt[],int n,point res[]) { int i,len,k=0,top=1; sort(pnt,pnt+n); if(n==0)return 0; res[0]=pnt[0]; if(n==1)return 1; res[1]=pnt[1]; if(n==2)return 2; res[2]=pnt[2]; for(i = 2; i < n; ++ i){ while(top && mult(pnt[i],res[top],res[top-1]))top--; res[++top]=pnt[i]; } len = top; res[++top]=pnt[n-2]; for(i=n-3;i>=0;--i){ while(top!=len&&mult(pnt[i],res[top],res[top-1]))top--; res[++top]=pnt[i]; } return top; } //判断两直线是否平行 bool px(point a,point b,point c,point d){ return (a.y-b.y)*(c.x-d.x)==(c.y-d.y)*(a.x-b.x); } //知直线ab,求直线cd,使得cd平行ab point getpoint(point c,point b,point a) { point d; if(a.x==b.x){ d.x = c.x; d.y = c.y + 1; return d; } d.x=c.x+1; d.y=(a.y-b.y)/(a.x-b.x)+c.y; return d; } //不直线与直线的交点 point intersection(point u1,point u2,point v1,point v2) { point ret = u1; double t = ((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x)); ret.x+=(u2.x-u1.x)*t; ret.y+=(u2.y-u1.y)*t; return ret; } int main() { int i,j,k,t,n,cas=0; scanf("%d",&t); while(t--){ scanf("%d",&n); for(i=0;i<n;++i)bs[i].scan(); n = graham(bs,n,as); as[n]=as[0]; for(i = 0; i < n; ++ i){ double mx=0,tmp; int idx; for(j=0;j<n;++j){ tmp=disptoline(as[j].x,as[j].y,as[i].x,as[i].y,as[i+1].x,as[i+1].y); if(tmp>mx)mx=tmp,idx=j; } dis[i]=idx; } double mx = 1e9; for(i=0;i<n;++i){ for(j=0;j<n;++j){ if(i==j||px(as[i],as[i+1],as[j],as[j+1]))continue; point a = getpoint(as[dis[i]],as[i],as[i+1]); point b = getpoint(as[dis[j]],as[j],as[j+1]); //bs[0]~bs[3]为平行四边形的四个顶点 bs[0] = intersection(as[i],as[i+1],as[j],as[j+1]); bs[1] = intersection(as[i],as[i+1],as[dis[j]],b); bs[2] = intersection(as[j],as[j+1],as[dis[i]],a); bs[3] = intersection(a,as[dis[i]],b,as[dis[j]]); double tmp=fabs((bs[0].x-bs[1].x)*(bs[2].y-bs[1].y)-(bs[2].x-bs[1].x)*(bs[0].y-bs[1].y)); if(tmp<mx)mx=tmp; } } printf("Swarm %d Parallelogram Area: %.4lf\n",++cas,mx); } return 0; }