Luogu3187[HNOI2007]最小矩形覆盖

Luogu3187[HNOI2007]最小矩形覆盖

题面:洛谷

解析

板题,旋转卡壳即可。

代码


// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define N 50005
using namespace std;
#define gc() getchar()
inline int In(){
    char c=gc(); int x=0,ft=1;
    for(;c<'0'||c>'9';c=gc()) if(c=='-') ft=-1;
    for(;c>='0'&&c<='9';c=gc()) x=x*10+c-'0';
    return x*ft;
}
const double eps=1e-6,Pi=acos(-1.0);
inline int dcmp(double x){
    if(fabs(x)<eps) return 0;
    else return x<0?-1:1;
}
struct Point{
    double x,y;
    Point(double x=0,double y=0):x(x),y(y) {}
    bool operator < (const Point& p) const { return dcmp(x-p.x)==0?y<p.y:x<p.x; }
}p[N],poi[N],q[5];
typedef Point Vector;
Vector operator + (Vector a,Vector b){ return Vector(a.x+b.x,a.y+b.y); }
Vector operator - (Vector a,Vector b){ return Vector(a.x-b.x,a.y-b.y); }
Vector operator * (Vector a,double p){ return Vector(a.x*p,a.y*p); }
Vector operator / (Vector a,double p){ return Vector(a.x/p,a.y/p); }
inline double Cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}
inline double Dot(Vector a,Vector b){
    return a.x*b.x+a.y*b.y;
}
inline double Len(Vector a){
    return sqrt(Dot(a,a));
}
inline double Dis(Point a,Point u,Point v){
    return fabs(Cross(a-u,v-u))/Len(v-u);
}
inline Point Get_Poi(Point P,Point A,Point B){
    Vector v=B-A;
    return A+v*(Dot(v,P-A)/Dot(v,v));
}
inline Vector Rotate(Vector a,double rad){
    return Vector(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
}
inline int ConvexHull(Point* p,int n,Point* ch){
    sort(p+1,p+1+n); int top=0;
    for(int i=1;i<=n;++i){
        while(top>1&&dcmp(Cross(ch[top]-ch[top-1],p[i]-ch[top-1]))<=0) --top;
        ch[++top]=p[i];
    }
    int k=top;
    for(int i=n-1;i;--i){
        while(top>k&&dcmp(Cross(ch[top]-ch[top-1],p[i]-ch[top-1]))<=0) --top;
        ch[++top]=p[i];
    }
    if(n>1) --top; return top;
}
inline void print(){
    for(int i=1;i<=4;++i) q[i].x=(int)(q[i].x+0.5),q[i].y=(int)(q[i].y+0.5);
    int w,x,y,z,flag=0; w=x=y=z=1;
    for(int i=2;i<=4;++i){
        if(q[i].y<q[w].y) w=i;
        if(q[i].y>q[x].y) x=i;
        if(q[i].x<q[y].x) y=i;
        if(q[i].x>q[z].x) z=i;
    }
    for(int i=1;i<=4;++i) if(i!=w&&dcmp(q[i].y-q[w].y)==0) flag=1;
    if(!flag){
        printf("%.5lf %.5lf\n",q[w].x,q[w].y);
        printf("%.5lf %.5lf\n",q[z].x,q[z].y);
        printf("%.5lf %.5lf\n",q[x].x,q[x].y);
        printf("%.5lf %.5lf\n",q[y].x,q[y].y);
    }
    else{
        sort(q+1,q+1+4);
        printf("%.5lf %.5lf\n",q[1].x,q[1].y);
        printf("%.5lf %.5lf\n",q[3].x,q[3].y);
        printf("%.5lf %.5lf\n",q[4].x,q[4].y);
        printf("%.5lf %.5lf\n",q[2].x,q[2].y);
    }
}
int main(){
//  freopen("4.in","r",stdin);
    int n=In();
    for(int i=1;i<=n;++i) scanf("%lf%lf",&poi[i].x,&poi[i].y);
    n=ConvexHull(poi,n,p); int w,x,y,z; w=x=y=z=1;
    for(int i=2;i<=n;++i){
        if(p[i].y<p[w].y) w=i;
        if(p[i].y>p[x].y) x=i;
        if(p[i].x<p[y].x) y=i;
        if(p[i].x>p[z].x) z=i;
    }
    p[n+1]=p[1]; double ans=1e9;
    for(int i=1;i<=n;++i){
        while(Dis(p[x],p[w],p[w+1])<Dis(p[x+1],p[w],p[w+1])) x=x%n+1;
        while(dcmp(Dot(p[y+1]-p[y],p[w+1]-p[w]))<0) y=y%n+1;
        while(dcmp(Dot(p[z+1]-p[z],p[w+1]-p[w]))>0) z=z%n+1;
        double S=Dis(p[x],p[w],p[w+1])*Dot(p[z]-p[y],p[w+1]-p[w])/Len(p[w+1]-p[w]);
        if(ans>S){
            Vector vec=Rotate(p[w+1]-p[w],Pi/2);
            q[1]=Get_Poi(p[y],p[w+1],p[w]);
            q[2]=Get_Poi(p[z],p[w+1],p[w]);
            q[3]=Get_Poi(p[x],q[1],q[1]+vec);
            q[4]=Get_Poi(p[x],q[2],q[2]+vec);
            ans=S;
        }
        w=w%n+1;
    }
    printf("%.5lf\n",ans); print();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/pkh68/p/10539668.html