P3187 [HNOI2007]最小矩形覆盖

传送门

首先这个矩形的一条边肯定在凸包上。那么可以求出凸包然后枚举边,用类似旋转卡壳的方法求出另外三条边的位置,也就是求出以它为底最上面最右边最左边的点的位置。离它最远的点可以用叉积求,最左最右的可以用点积求。顺便注意精度问题,因为很小的时候可能会输出-0.00000,所以特判一下,当坐标小于eps的时候强制它等于0就行了

//minamoto
#include<bits/stdc++.h>
#define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define ab(a) (a<0?a=-a:0)
using namespace std;
const int N=1e5+5;const double eps=1e-8;
struct node{double x,y;}p[N],st[N],q[5];int top,n;
inline node operator -(node a,node b){return node{a.x-b.x,a.y-b.y};}
inline node operator +(node a,node b){return node{a.x+b.x,a.y+b.y};}
inline node operator *(node a,double b){return node{a.x*b,a.y*b};}
inline double operator *(node a,node b){return a.x*b.y-b.x*a.y;}
inline double dot(node a,node b){return a.x*b.x+a.y*b.y;}
inline double area(node a,node b,node c){return fabs((b-a)*(c-a));}
inline double len(node a){return sqrt(a.x*a.x+a.y*a.y);}
inline bool operator <(node a,node b){
    a=a-p[1],b=b-p[1];
    return a*b==0?len(a)<len(b):a*b>0;
}
void graham(){
    int k=1;
    fp(i,1,n){
        scanf("%lf%lf",&p[i].x,&p[i].y);
        if(p[i].y<p[k].y||(p[i].y==p[k].y&&p[i].x<p[k].x))k=i;
    }swap(p[1],p[k]),sort(p+2,p+n+1);
    st[0]=p[1],st[1]=p[2],top=1;
    fp(i,3,n){
        while(top&&(p[i]-st[top-1])*(st[top]-st[top-1])>=0)--top;
        st[++top]=p[i];
    }st[++top]=p[1];
//  fp(i,0,top)printf("%.2lf %.2lf\n",st[i].x,st[i].y);
}
void get(){
    double ans=1e100;int a=1,b=1,c=1;
    fp(i,1,top-2){
        while((st[a+1]-st[i])*(st[i-1]-st[i])>=(st[a]-st[i])*(st[i-1]-st[i]))a=(a+1)%top;
        while(dot(st[b+1]-st[i],st[i-1]-st[i])<=dot(st[b]-st[i],st[i-1]-st[i]))b=(b+1)%top;
        if(i==1)c=a;
        while(dot(st[c+1]-st[i-1],st[i]-st[i-1])<=dot(st[c]-st[i-1],st[i]-st[i-1]))c=(c+1)%top;
        double dis=len(st[i]-st[i-1]);
        double L=dot(st[c]-st[i],st[i-1]-st[i])/dis;ab(L);
        double R=dot(st[b]-st[i-1],st[i]-st[i-1])/dis;ab(R);
        double H=area(st[i],st[i-1],st[a])/dis;ab(H);
        double tmp=(L+R-dis)*H;
        if(tmp<ans){
            ans=tmp;
            q[0]=st[i]-(st[i]-st[i-1])*(L/dis);
            q[1]=q[0]+(st[i]-st[i-1])*((L+R-dis)/dis);
            q[2]=q[1]+(st[b]-q[1])*(H/len(st[b]-q[1]));
            q[3]=q[2]+(st[i-1]-st[i])*((L+R-dis)/dis);
        }
    }printf("%.5lf\n",ans);
}
int main(){
//  freopen("testdata.in","r",stdin);
    scanf("%d",&n);graham();get();
    int s=0;
    fp(i,0,3)if(q[i].y<q[s].y||(q[i].y==q[s].y&&q[i].x<q[s].x))s=i;
    if(fabs(q[s].x)<=eps)q[s].x=0;if(fabs(q[s].y)<=eps)q[s].y=0;
    printf("%.5lf %.5lf\n",q[s].x,q[s].y);
    fp(i,1,3){
        s=(s+1)%4;
        if(fabs(q[s].x)<=eps)q[s].x=0;if(fabs(q[s].y)<=eps)q[s].y=0;
        printf("%.5lf %.5lf\n",q[s].x,q[s].y);
    }return 0;
}

猜你喜欢

转载自www.cnblogs.com/bztMinamoto/p/10009640.html