POJ 2079 旋转卡壳

//check if all is d_ ,convenient to double &&long double
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#include<set>
#include<algorithm>
#define sqr(x) (x)*(x)
#define f1 first
#define f2 second
#define pb push_back
#define fr(i,x,y) for(int i=x;i<=y;++i)
#define sqr(x) (x)*(x)
typedef double d_;
const d_ pi=acos(-1.0);
using namespace std;


struct Point{
    d_ x,y;
    Point(d_ x=0,d_ y=0):x(x),y(y){}
    void read(){scanf("%lf%lf",&x,&y);}//lf or LF
    void print(){printf("~~~~~~%lf %lf\n",x,y);}//lf or LF
};
struct Point3{
    d_ x,y,z;
    Point3(d_ x=0,d_ y=0,d_ z=0):x(x),y(y),z(z){}
    void read(){scanf("%lf%lf%lf",&x,&y,&z);}//lf or LF
    void print(){printf("~~~~~~%lf %lf %lf\n",x,y,z);}//lf or LF
};
typedef Point Vector;
typedef Point3 Vector3;
const d_ eps=1e-8;
int dcmp(d_ x){
    if (fabs(x)<eps)  return 0;else return x<0?-1:1;}
inline double ensure_asin(double t){if (fabs(t+1)<eps||fabs(t-1)<eps)t=floor(t+0.5);return t;}
inline double ensure_acos(double t){if (fabs(t+1)<eps||fabs(t-1)<eps)t=floor(t+0.5);return t;}
inline void ensure_atan2(Vector &v){if (fabs(v.y)<eps)v.y=eps;}


inline Vector operator+(Vector a,Vector b) {return Vector(a.x+b.x,a.y+b.y);}
inline Vector operator-(Vector a,Vector b) {return Vector(a.x-b.x,a.y-b.y);}
inline Vector operator*(Vector a,d_ p) {return Vector(a.x*p  ,a.y*p);  }
inline Vector operator*(d_ p,Vector a) {return Vector(a.x*p  ,a.y*p);  }
inline Vector operator/(Vector a,d_ p) {return Vector(a.x/p  ,a.y/p);  }
Vector3 operator+(Vector3 a,Vector3 b) {return Vector3(a.x+b.x,a.y+b.y,a.z+b.z);}
Vector3 operator-(Vector3 a,Vector3 b) {return Vector3(a.x-b.x,a.y-b.y,a.z-b.z);}
Vector3 operator*(Vector3 a,d_ p) {return Vector3(a.x*p  ,a.y*p,a.z*p);  }
Vector3 operator*(d_ p,Vector3 a) {return Vector3(a.x*p  ,a.y*p,a.z*p);  }
Vector3 operator/(Vector3 a,d_ p) {return Vector3(a.x/p  ,a.y/p,a.z/p);  }
d_ cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
d_ operator*(const Vector &a,const Vector&b){return a.x*b.y-a.y*b.x;}
d_ cross(Point a,Point b,Point c){return (b-a)*(c-a);}
d_ dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
d_ operator%(const Vector &a,const Vector&b){return a.x*b.x+a.y*b.y;}
Vector3 cross(Vector3 a,Vector3 b){
    return Vector3(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
}
Vector3 operator*(const Vector3 &a,const Vector3&b){
    return Vector3(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
}
d_ dot(Vector3 a,Vector3 b){return a.x*b.x+a.y*b.y+a.z*b.z;}
d_ operator%(const Vector3 &a,const Vector3&b){return a.x*b.x+a.y*b.y+a.z*b.z;}
bool operator<(const Point &a,const Point&b)
{
    return dcmp(a.x-b.x)<0||(dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)<0);
}
bool operator==(const Point &a,const Point&b) {return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;}
bool operator<(const Point3 &a,const Point3 &b)
{
    return dcmp(a.x-b.x)<0||(dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)<0)||(dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0&&dcmp(a.z-b.z)<0);
}
bool operator==(const Point3 &a,const Point3&b) {return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0&&dcmp(a.z-b.z)==0;}
//---------------------------------


inline d_ length(Vector a) {return sqrt(dot(a,a));}
d_ angle(Vector a,Vector b){return acos(ensure_acos(dot(a,b)/length(a)/length(b)));}
d_ area2(Point a,Point b,Point c){return cross(b-a,c-a);}
d_ dist(Point &a,Point &b){return length(b-a);}
Vector rotate(Vector a,d_ rad)
{   return Vector(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
}
Vector normal(Vector a)//ensure a!=(0,0)
{   d_ l=length(a);
    return Vector(-a.y/l,a.x/l);
}
d_ length(Vector3 a) {return sqrt(dot(a,a));}
d_ dist(Point3 &a,Point3 &b){return length(b-a);}
//--------------------------------------------------------------
struct Line{
    Point p;
    Vector v;
    d_ ang;
    Line(){}
    Line(Point p,Vector v):p(p),v(v){ensure_atan2(v);ang=atan2(v.y,v.x);}
    bool operator<(const Line &l)const{return ang<l.ang;}
    Point getPoint(d_ t)
    {
        return p+v*t;
    }
    d_ getabc(d_ A,d_ B,d_ C)
    {
        A=-v.y;
        B=v.x;
        C=p.x*(v.y+p.y)-p.y*(p.x+v.x);

    }
    //两直线相交求交点
    //第一个值为0表示直线重合,为1表示平行,为2是相交
    //只有第一个值为2时,交点才有意义
    pair<int,Point> operator &(const Line &b)const
    {
        Point res = p;
        if(dcmp(v*b.v) == 0)
        {
            if(dcmp((p-b.p)*b.v) == 0)
                return make_pair(0,res);//重合
            else return make_pair(1,res);//平行
        }
        d_ t = (b.v*(p-b.p))/(v*b.v);
        res=res+t*v;
        return make_pair(2,res);
    }
};

struct Circle{
    Point c;
    d_ r;
    Circle(){}
    Circle(Point c,d_ r):c(c),r(r){}
    Point getPoint(d_ a)
    {
        return Point(c.x+cos(a)*r,c.y+sin(a)*r);
    }
    void read()
    {
        scanf("%lf%lf%lf",&c.x,&c.y,&r);//lf or LF
    }
};
Point get_Line_intersection(Point p,Vector v,Point q,Vector w){
    Vector u=p-q;
    d_ t=cross(w,u)/cross(v,w);
    return p+v*t;
}
d_ distance_to_Line(Point p,Point a,Point b)//p to Line(ab)
{
    Vector v1=b-a,v2=p-a;
    return fabs(cross(v1,v2))/length(v1);
}
inline d_ distance_to_segment(Point p,Point a,Point b)
{
    if (a==b) return length(p-a);
    Vector v1=b-a,v2=p-a,v3=p-b;
    if (dcmp(dot(v1,v2))<0)  return length(v2);
    if (dcmp(dot(v1,v3))>0)  return length(v3);
    return fabs(cross(v1,v2))/length(v1);
}
d_ distance_seg_to_seg(Point A,Point B,Point C,Point D)
{
    return min(min(distance_to_segment(C,A,B),distance_to_segment(D,A,B)),min(distance_to_segment(A,C,D),distance_to_segment(B,C,D)));
}
Point get_Line_projection(Point p,Point a,Point b)
{
    Vector v=b-a;
    return a+v*(dot(v,p-a)/dot(v,v));
}
bool segment_proper_intersection(Point a1,Point a2,Point b1,Point b2)//ensure line(a1,a2)!=line(b1,b2)
{
    d_ c1=cross(a2-a1,b1-a1),c2=cross(a2-a1,b2-a1);
    d_ c3=cross(b2-b1,a1-b1),c4=cross(b2-b1,a2-b1);
    return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;
}

bool Point_on_line(Point p,Point a,Point b){
    return dcmp(cross(a-p,b-p))==0;
}
bool on_segment(Point p,Point a,Point b)
{
    return dcmp(cross(a-p,b-p))==0&&dcmp(dot(a-p,b-p))<0;
}
bool notstrict_on_segment(Point p,Point a,Point b)
{
    return dcmp(cross(a-p,b-p))==0&&dcmp(dot(a-p,b-p))<=0;
}
//--------------------------------
int get_Line_Circle_intersection(Line l,Circle c,d_ &t1,d_ &t2,vector<Point>&sol)
{
    d_ a=l.v.x,b=l.p.x-c.c.x,cc=l.v.y,d=l.p.y-c.c.y;
    d_ e=a*a+cc*cc,f=2*(a*b+cc*d), g=b*b+d*d-c.r*c.r;
    d_ delta=f*f-4*e*g;
    if (dcmp(delta)<0) return 0;
    if (dcmp(delta)==0) {
        t1=t2=-f/(2*e); sol.pb(l.getPoint(t1));
        return 1;
    }
    t1=(-f-sqrt(delta))/(2*e); sol.pb(l.getPoint(t1));
    t2=(-f+sqrt(delta))/(2*e); sol.pb(l.getPoint(t2));
    return 2;
}
d_ angle(Vector v)
{   return atan2(v.y,v.x);
}

int get_Circle_Cirlce_intersection(Circle c1,Circle c2,vector<Point>&sol)
{
    d_ d=length(c1.c-c2.c);
    if (dcmp(d)==0)
        {
            if (dcmp(c1.r-c2.r)==0) return -1;
            return 0;
        }
    if (dcmp(c1.r+c2.r-d)<0) return 0;
    if (dcmp(fabs(c1.r-c2.r)-d)>0) return 0;

    d_ a=angle(c2.c-c1.c);
    d_ da=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
    Point p1=c1.getPoint(a-da),p2=c1.getPoint(a+da);
    sol.pb(p1);
    if (p1==p2) return 1;
    sol.pb(p2);
    return 2;
}

int get_tangents1(Point p ,Circle c,vector<Vector>&sol)
{
    Vector u=c.c-p;
    d_ dist=length(u);
         if (dist<c.r) return 0;
    else if (dcmp(dist-c.r)==0)
        {
            sol.pb(rotate(u,pi/2));
            return 1;
        }
    else{   d_ ang=asin(c.r/dist);
            sol.pb(rotate(u,-ang));
            sol.pb(rotate(u,ang));
            return 2;
        }
}

int get_tangents2(Circle ca,Circle cb,Point *a,Point *b)
{
    int cnt=0;
    if (ca.r<cb.r) {swap(ca,cb);
                    swap(a,b);
                   }
    int d2=sqr(ca.c.x-cb.c.x)+sqr(ca.c.y-cb.c.y);
    int rdiff=ca.r-cb.r;
    int rsum=ca.r+cb.r;
    if (d2<rdiff*rdiff) return 0;

    d_ base=atan2(cb.c.y-ca.c.y,cb.c.x-ca.c.x);
    if (d2==0&&ca.r==cb.r) return -1;
    if (d2==rdiff*rdiff)
        {   a[cnt]=ca.getPoint(base); b[cnt]=cb.getPoint(base); cnt++;
            return 1;
        }

    d_ ang=acos((ca.r-cb.r)/sqrt(double(d2)));
    a[cnt]=ca.getPoint(base+ang); b[cnt]=cb.getPoint(base+ang);  cnt++;
    a[cnt]=ca.getPoint(base-ang); b[cnt]=cb.getPoint(base-ang);  cnt++;
    if (d2==rsum*rsum)
        {
            a[cnt]=ca.getPoint(base);
            b[cnt]=cb.getPoint(pi+base);
            cnt++;
        }
    else if (d2>rsum*rsum)
        {
            d_ ang=acos((ca.r+cb.r)/sqrt(double(d2)));
            a[cnt]=ca.getPoint(base+ang); b[cnt]=cb.getPoint(base+pi+ang);  cnt++;
            a[cnt]=ca.getPoint(base-ang); b[cnt]=cb.getPoint(base+pi-ang);  cnt++;
        }
    return cnt;
}


bool segment_intersection(Point a,Point b,Point c,Point d)//have and only one intersection
{
    Line l1(a,b-a),l2(c,d-c);
    if ((l1&l2).first==0)
    {
        if (a==c&&!on_segment(b,c,d)&&!on_segment(d,a,b))return 1;
        if (a==d&&!on_segment(b,c,d)&&!on_segment(c,a,b))return 1;
        if (b==c&&!on_segment(a,c,d)&&!on_segment(d,a,b))return 1;
        if (b==d&&!on_segment(a,c,d)&&!on_segment(c,a,b))return 1;
        return 0;
    }
   if (segment_proper_intersection(a,b,c,d)||on_segment(a,c,d)||on_segment(b,c,d)||on_segment(c,a,b)||on_segment(d,a,b)||(a==c)||(a==d)||(b==c)||(b==d))
   return 1;else return 0;
}
bool segment_notproper_intersection(Point a,Point b,Point c,Point d)//have at least one intersection
{
    Line l1(a,b-a),l2(c,d-c);
    if ((l1&l2).first==0)
    {
        if (a==c||a==d||b==c||b==d) return 1;
        if (on_segment(a,c,d)||on_segment(b,c,d)||on_segment(c,a,b)||on_segment(d,a,b)==1)return 1;
        return 0;
    }
   if (segment_proper_intersection(a,b,c,d)||on_segment(a,c,d)||on_segment(b,c,d)||on_segment(c,a,b)||on_segment(d,a,b)||(a==c)||(a==d)||(b==c)||(b==d))
   return 1;else return 0;
}
int n;

d_ polygon_area(Point *p,int n)
{
    d_ re=0;
    fr(i,1,n-2)
        re+=(p[i]-p[0])*(p[i+1]-p[0]);
    return re;
}

Point bcenter1(Point *p,int n)
{
    d_ area=0,tt;
    Point t,s,ans(0,0);
    t=p[0];
    fr(i,1,n)
        {
            s=p[(i==n)?0:i];
            tt=t*s;area+=tt;
            ans=ans+(t+s)*tt;
            t=s;
        }
    ans=ans/(area*3);
    return ans;
}
Point bcenter2(Point *p,int n)
{
    d_ area=0,tt;
    Point t,s,ans(0,0);
    fr(i,1,n-2)
        {
            tt=(p[i]-p[0])*(p[i+1]-p[0]);
            ans=ans+(p[i]+p[i+1]+p[0])*tt;
            area+=tt;
        }
    ans=ans/(area*3);
    return ans;
}
int is_point_in(Point p,Point poly[],int n)
{
    int w=0;
    fr (i,0,n-1)
        {
            if (notstrict_on_segment(p,poly[i],poly[(i+1)%n])) return -1;
            int k=dcmp((poly[(i+1)%n]-poly[i])*(p-poly[i]));
            int d1=dcmp(poly[i].y-p.y);
            int d2=dcmp(poly[(i+1)%n].y-p.y);
            if (k>0&&d1<=0&&d2>0)w++;
            if (k<0&&d2<=0&&d1>0)w--;
        }
    return (w!=0);
}
//判断直线ab是否与线段cd相交
//0 不相交
//1 规范相交
//2 不规范相交
int seg(const Point& a,const Point& b,const Point& c,const Point& d)
{
    int d1,d2;
    d1 = dcmp((b-a)*(c-a));
    d2 = dcmp((b-a)*(d-a));
    if(d1*d2<0)
        return 1;
    if(d1==0||d2==0)
        return 2;
    return 0;
}


int convex(Point* st,int n,Point *ps)
{
    int k=0;
    sort(st,st+n);
    for (int i=0;i<n;i++)
        {   while (k>1&&(ps[k-1]-ps[k-2])*(st[i]-ps[k-2])<=0) k--;
            //若想含边上的点,可以将<=改成<
            ps[k++]=st[i];
            //printf("~~i=%d k=%d\n",i,k);
        }
    for (int i=n-2,t=k;i>=0;i--)
        {   while (k>t&&(ps[k-1]-ps[k-2])*(st[i]-ps[k-2])<=0) k--;
            ps[k++]=st[i];
            //printf("!!i=%d k=%d\n",i,k);
        }
    if (n>1)k--;
    return k;
}
bool onleft(Line l,Point p)
{
    return dcmp(l.v*(p-l.p))>0;
}
int half_plane_intersection(Line *l,int n,Point*poly)
{
    sort(l,l+n);
    int fir,last;
    Point *p=new Point[n];
    Line *q=new Line[n];
    q[fir=last=0]=l[0];
    fr(i,1,n-1)
        {
            while (fir<last&&!onleft(l[i],p[last-1])) last--;
            while (fir<last&&!onleft(l[i],p[fir])) fir++;
            q[++last]=l[i];
            if (fabs(q[last].v*q[last-1].v)<eps)
                {     if (dcmp(q[last].v%q[last-1].v)<=0){last--;continue;}
                      last--;
                      if(onleft(q[last],l[i].p) )q[last]=l[i];
                }
            if (fir<last)
                p[last-1]=get_Line_intersection(q[last-1].p,q[last-1].v,q[last].p,q[last].v);
        }
    while (fir<last&&!onleft(q[fir],p[last-1]))last--;
    if (last-fir<=1){delete p;delete q;return 0;}
    p[last]=get_Line_intersection(q[last].p,q[last].v,q[fir].p,q[fir].v);
    if (!onleft(q[last-1],p[last])){delete p;delete q;return -1;}
    int m=0;
    fr(i,fir,last) poly[m++]=p[i];
    delete p;
    delete q;
    return m;
}
struct Poly {
    vector<Point> pt;
    Poly() { pt.clear();}
    Poly(vector<Point> &pt) : pt(pt) {}
    Point operator [] (int x) const { return pt[x];}
    int size() { return pt.size();}
    double area()
        {   int n=size();
            d_ re=0;
            fr(i,1,n-2)
                re+=(pt[i]-pt[0])*(pt[i+1]-pt[0]);
            return fabs(re/2.0);
        }
 };
int ptInPoly(Point p, Poly &poly) {
 int wn = 0, sz = poly.size();
 for (int i = 0; i < sz; i++) {
 if (on_segment(p, poly[i], poly[(i + 1) % sz])) return -1;
 int k = dcmp(cross(poly[(i + 1) % sz] - poly[i], p - poly[i]));
 int d1 = dcmp(poly[i].y - p.y);
 int d2 = dcmp(poly[(i + 1) % sz].y - p.y);
 if (k > 0 && d1 <= 0 && d2 > 0) wn++;
 if (k < 0 && d2 <= 0 && d1 > 0) wn--;
 }
 if (wn != 0) return 1;
 return 0;
 }
bool isIntersect(Point a, Point b, Poly &poly)
{   int sz=poly.size();
    fr (i,0,sz-1)
    if (segment_intersection(a, b, poly[i],poly[(i+1)%n])) return 1;
    return 0;
 }
Poly cutPoly(Poly &poly, Point a, Point b)
{
    int n=poly.size();
    Poly npoly=Poly();
    fr(i,0,n-1)
        {
            Point c=poly[i],d=poly[(i+1)%n];
            if (dcmp((b-a)*(c-a))>=0) npoly.pt.pb(c);
            if (dcmp((b-a)*(c-d))!=0)
                {
                    Point ip=get_Line_intersection(a,b-a,c,d-c);
                    if (on_segment(ip,c,d))npoly.pt.pb(ip);
                }
        }
    return npoly;
}


 vector<Poly> cutPolies(Point s, Point t, vector<Poly> polies) {
    vector<Poly> ret;
    ret.clear();
    for (int i = 0, sz = polies.size(); i < sz; i++)
    {
    Poly tmp;
    tmp = cutPoly(polies[i], s, t);
    if (tmp.size() >= 3 && tmp.area() > eps) ret.push_back(tmp);
    tmp = cutPoly(polies[i], t, s);
    if (tmp.size() >= 3 && tmp.area() > eps) ret.push_back(tmp);
    }
    return ret;
 }





double rotating_calipers(Point *p1,Point *p2,int top1,int top2)
{
    int s1=0,s2=0;
    for(int i=1;i<top1;i++)
        if(dcmp(p1[i].y-p1[s1].y)<0||(dcmp(p1[i].y-p1[s1].y)==0)&&dcmp(p1[i].x-p1[s1].x)<0) s1=i;
    for(int i=1;i<top2;i++)
        if(dcmp(p2[i].y-p2[s2].y)>0||(dcmp(p2[i].y-p2[s2].y)==0)&&dcmp(p2[i].x-p2[s2].x)>0) s2=i;
    int t1=s1,t2=s2;
    double ans=length(p1[s1]-p2[s2]);
    int nn=0;
    do
    {
        double af=(p1[(s1+1)%top1]-p1[s1])*(p2[(s2+1)%top2]-p2[s2]);
        if(dcmp(af)==0)//卡壳到两条边
        {
            ans=min(ans,distance_to_segment(p1[s1],p2[s2],p2[(s2+1)%top2]));
            ans=min(ans,distance_to_segment(p1[(s1+1)%top1],p2[s2],p2[(s2+1)%top2]));
            ans=min(ans,distance_to_segment(p2[s2],p1[s1],p1[(s1+1)%top1]));
            ans=min(ans,distance_to_segment(p2[(s2+1)%top2],p1[s1],p1[(s1+1)%top1]));
            s1=(s1+1)%top1; s2=(s2+1)%top2;
        }
        else if(dcmp(af)<0)//卡壳到第一个的边,第二个的点
        {
            ans=min(ans,distance_to_segment(p2[s2],p1[s1],p1[(s1+1)%top1]));
            s1=(s1+1)%top1;
        }
        else//卡壳到第二个的边,第一个的点
        {
            ans=min(ans,distance_to_segment(p1[s1],p2[s2],p2[(s2+1)%top2]));
            s2=(s2+1)%top2;
        }
    }while(t1!=s1||t2!=s2);
    return ans;
}


double ro(int n,Point *p)
{
    int i,j,k;
    double ar=0;
    for (i=0;i<n;i++)
        {
            j=(i+1)%n;k=(j+1)%n;
            double c1,c2;
            while (k!=i)
            {
                double c1=cross(p[i],p[j],p[k]),c2=cross(p[i],p[j],p[(k+1)%n]);
                if (dcmp(c1-c2)<0) k=(k+1)%n;else break;
            }
            if (k==i)continue;
            int kk =(k+1)%n;
            while (j!=kk&&k!=i)
                {
                   double c1=cross(p[i],p[j],p[k]);
                    ar=max(ar,c1);
                    while (k!=i)
                    {
                        double c1=cross(p[i],p[j],p[k]),c2=cross(p[i],p[j],p[(k+1)%n]);
                        if (dcmp(c1-c2)<0) k=(k+1)%n;else break;
                    }
                    j=(j+1)%n;
                }
        }
        return ar/2;
}
#define N 50005
Point aa[N],a[N];
void doit()
{
    fr(i,0,n-1)aa[i].read();
    n=convex(aa,n,a);
    printf("%.2lf\n",ro(n,a));
}
int main()
{
    int cas;
    while (scanf("%d",&n),n!=-1) doit();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值