BZOJ 1185 [HNOI2007]最小矩形覆盖 ——计算几何

程序写的太垃圾,卡不过去。

GG,甘拜下风。

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
//#define double long double
#define eps 1e-8
#define ll long long
#define mp make_pair
 
struct Vector{
    double x,y;
    void print()
    {
        printf("Vector -> (%.3f,%.3f)\n",x,y);
    }
};
 
struct Point{
    double x,y;
    void print()
    {
        printf("%.5f %.5f\n",x+eps,y+eps);
    }
};
 
int n;
 
Vector operator - (Point a,Point b)
{Vector ret;ret.x=a.x-b.x;ret.y=a.y-b.y;return ret;}
 
Point operator + (Point a,Vector b)
{Point ret;ret.x=a.x+b.x;ret.y=a.y+b.y;return ret;}
 
Vector Vertical (Vector a)
{Vector ret;ret.x=-a.y;ret.y=a.x;return ret;}
 
double operator * (Vector a,Vector b)
{return a.x*b.y-a.y*b.x;}
 
Vector operator * (Vector a,double b)
{Vector ret;ret.x=a.x*b;ret.y=a.y*b;return ret;}
 
Point Node (Point P1,Vector V1,Point P2,Vector V2)
{return P1+V1*((V2*(P1-P2))/(V1*V2));}
 
Point a[50005];
 
void Test()
{
    printf("Test : \n");
    Point P1,P2;Vector V1,V2;
    P1.x=0;P1.y=1;V1.x=1;V1.y=1;
    P2.x=1;P2.y=0;V2.x=1;V2.y=2;
    Node(P1,V1,P2,V2).print();
}
 
bool cmp(Point a,Point b)
{return fabs(a.x-b.x)<eps?a.y<b.y:a.x<b.x;}
 
Point sta[50005];
int top=0;
 
void Andrew()
{
    sta[++top]=a[1];
    F(i,2,n)
    if (fabs(a[i].x-a[i-1].x)>=eps||fabs(a[i].y-a[i-1].y)>=eps){
        while (top>=2&&(sta[top]-sta[top-1])*(a[i]-sta[top])<0) top--;
        sta[++top]=a[i];
    }
    int lower=top;
    D(i,n-1,1)
    if (fabs(a[i].x-a[i+1].x)>=eps||fabs(a[i].y-a[i+1].y)>=eps){
        while (top-lower>=1&&(sta[top]-sta[top-1])*(a[i]-sta[top])<0) top--;
        sta[++top]=a[i];
    }
}
 
double Dot(Vector a,Vector b)
{return a.x*b.x+a.y*b.y;}
 
double Len(Vector a)
{
    return Dot(a,a);
}
 
void Finout()
{
    freopen("in.txt","r",stdin);
}
 
Point now[4],ans[4];
double tmp=1e18,nowans;
 
void Rotating()
{
    int l=top-1,r=3,p=2;
    while (Dot(sta[2]-sta[1],sta[l]-sta[1])>Dot(sta[2]-sta[1],sta[l-1]-sta[1])) l--;
    while (Dot(sta[2]-sta[1],sta[r]-sta[1])<Dot(sta[2]-sta[1],sta[r+1]-sta[1])) r++;
    F(i,1,top-1)
    {
        while (Dot(sta[i+1]-sta[i],sta[l]-sta[i])>Dot(sta[i+1]-sta[i],sta[l+1]-sta[i])) l=l%top+1;
        while (Dot(sta[i+1]-sta[i],sta[r]-sta[i])<Dot(sta[i+1]-sta[i],sta[r+1]-sta[i])) r=r%top+1;
        while ((sta[i+1]-sta[i])*(sta[p]-sta[i])<(sta[i+1]-sta[i])*(sta[p+1]-sta[i])) p=p%top+1;
        now[0]=Node(sta[i],sta[i+1]-sta[i],sta[l],Vertical(sta[i+1]-sta[i]));
        now[1]=Node(sta[i],sta[i+1]-sta[i],sta[r],Vertical(sta[i+1]-sta[i]));
        now[2]=Node(sta[p],sta[i+1]-sta[i],sta[r],Vertical(sta[i+1]-sta[i]));
        now[3]=Node(sta[p],sta[i+1]-sta[i],sta[l],Vertical(sta[i+1]-sta[i]));
        if ((nowans=sqrt(Len(now[0]-now[1])*Len(now[1]-now[2])))<tmp)
        {
            F(j,0,3) ans[j]=now[j];
            tmp=nowans;
        }
    }
    int st=-1;Point stp;
    stp.x=1e18;stp.y=1e18;
    F(i,0,3)
        if (fabs(ans[i].y-stp.y)<eps?ans[i].x<stp.x:ans[i].y<stp.y)
            st=i,stp=ans[i];
    printf("%.5f\n",tmp+eps);
    F(i,0,3) ans[(i+st)%4].print();
}
 
int main()
{
    scanf("%d",&n);
    F(i,1,n) scanf("%lf%lf",&a[i].x,&a[i].y);
    sort(a+1,a+n+1,cmp);
    Andrew();
    Rotating();
}

  

posted @ 2017-04-09 20:27  SfailSth  阅读(135)  评论(0编辑  收藏  举报