[省选前题目整理][BZOJ 1185][HNOI 2007]最小矩形覆盖(旋转卡壳)

来源:互联网 发布:搜狗抢票软件老是退出 编辑:程序博客网 时间:2024/05/19 21:43

题目链接

http://www.lydsy.com/JudgeOnline/problem.php?id=1185

思路

http://blog.csdn.net/qpswwww/article/details/44102039

代码

#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <algorithm>#include <cmath>#define MAXN 1000000#define EPS 1e-7using namespace std;int n;double minsqr=1e20;int dcmp(double x){    if(fabs(x)<EPS) return 0;    if(x>EPS) return 1;    return -1;}struct Point{    double x,y;    Point(){}    Point(double _x,double _y):x(_x),y(_y){}    inline void read()    {        scanf("%lf%lf",&x,&y);    }}points[MAXN],stack[MAXN<<1],ans[10];int top=0;Point operator-(Point a,Point b){    return Point(a.x-b.x,a.y-b.y);}Point operator*(Point a,double b){    return Point(a.x*b,a.y*b);}Point operator+(Point a,Point b){    return Point(a.x+b.x,a.y+b.y);}double cross(Point a,Point b,Point c) //a->b X a->c{    return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);}double dot(Point a,Point b,Point c) //a->b 点乘 b->c{    return (b.x-a.x)*(c.x-b.x)+(b.y-a.y)*(c.y-b.y);}double dist(Point a,Point b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}bool cmp(Point a,Point b){    if(!dcmp(a.x-b.x)) return a.y<b.y;    return a.x<b.x;}void Graham(){    sort(points+1,points+n+1,cmp);    for(int i=1;i<=n;i++)    {        while(top>=2&&dcmp(cross(stack[top-1],stack[top],points[i]))<=0) top--;        stack[++top]=points[i];    }    int tmp=top;    for(int i=n-1;i>=1;i--)    {        while(top>=tmp+1&&dcmp(cross(stack[top-1],stack[top],points[i]))<=0) top--;        stack[++top]=points[i];    }    top--; //stack[1]=stack[top]}void rotcalip(){    int left=1,right=1,up=1; //矩形卡在凸包上的左、右、上三个点,下面的是一条长度为L直线    for(int i=1;i<=top;i++)    {        while(dcmp(cross(stack[up+1],stack[i],stack[i+1])-cross(stack[up],stack[i],stack[i+1]))>=0) up=up%top+1;        while(dcmp(dot(stack[right+1],stack[i+1],stack[i])-dot(stack[right],stack[i+1],stack[i]))>=0) right=right%top+1; //!!!!!        if(i==1) left=right;        while(dcmp(dot(stack[left+1],stack[i],stack[i+1])-dot(stack[left],stack[i],stack[i+1]))>=0) left=left%top+1; //!!!!!!        double L=dist(stack[i],stack[i+1]);        double H=cross(stack[i+1],stack[up],stack[i])/L;        double bottom=(fabs(dot(stack[i],stack[i+1],stack[left])/L)+fabs(dot(stack[i],stack[i+1],stack[right])/L));        double nowsqr=bottom*H;        if(nowsqr<minsqr)        {            minsqr=nowsqr;            ans[0]=stack[i]+(stack[i+1]-stack[i])*((fabs(dot(stack[i],stack[i+1],stack[right])/L)+L)/L);            ans[1]=ans[0]+(stack[right]-ans[0])*(H/dist(stack[right],ans[0]));            ans[2]=ans[1]+(stack[up]-ans[1])*(bottom/dist(stack[up],ans[1]));            ans[3]=ans[2]+(stack[left]-ans[2])*(H/dist(stack[left],ans[2]));        }    }}bool operator<(Point a,Point b){    if(!dcmp(a.y-b.y)) return a.x<b.x;    return a.y<b.y;}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)        points[i].read();    Graham();    rotcalip();    printf("%.5lf\n",minsqr);    int tmp=0;    for(int i=0;i<=3;i++)        if(ans[i]<ans[tmp])            tmp=i;    for(int i=0;i<=3;i++)        printf("%.5lf %.5lf\n",ans[(i+tmp)%4].x,ans[(i+tmp)%4].y); //!!!!    return 0;}
0 0
原创粉丝点击