【旋转卡壳+凸包】BZOJ1185:[HNOI2007]最小矩形覆盖

1185: [HNOI2007]最小矩形覆盖

Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge
Submit: 1945  Solved: 853
[Submit][Status][Discuss]

Description

 

题解

显然矩形一边一定在凸包一边上

旋转卡壳维护其他三条边经过的顶点

更新答案

这题1A欸嘿嘿

代码

//by 减维
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<bitset>
#include<set>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<ctime>
#include<algorithm>
#define LL long long
#define db double
#define inf 1<<30
#define maxn 50005
#define eps 1e-8
using namespace std;

struct node{
    db x,y;
}poi[maxn],sta[maxn],ans[15];

int n,top;
db mn=100000000.00;

bool cmp(node x,node y){if(x.x==y.x)return x.y<y.y;return x.x<y.x;}
bool cm2(node x,node y){if(x.x==y.x)return x.y>y.y;return x.x>y.x;}
node operator - (node x,node y){return (node){x.x-y.x,x.y-y.y};}
node operator + (node x,node y){return (node){x.x+y.x,x.y+y.y};}
node operator * (node x,db y){return (node){x.x*y,x.y*y};}
node operator * (db x,node y){return (node){x*y.x,x*y.y};}
db operator * (node x,node y){return x.x*y.y-x.y*y.x;}
db operator / (node x,node y){return x.x*y.x+x.y*y.y;}
bool operator == (node x,node y){return x.x==y.x&&x.y==y.y;}
bool operator > (node x,node y){if(x.y==y.y)return x.x>x.y;return x.y>y.y;}
db dis(node x,node y){return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));}

void solve()
{
    db ds,h,ll,rr;
    int t=0,l=0,r=0;
    sta[0]=sta[top];
    for(int i=0;i<top;++i)
    {
        ds=dis(sta[i],sta[i+1]);
        while((sta[i+1]-sta[i])*(sta[t+1]-sta[i])-(sta[i+1]-sta[i])*(sta[t]-sta[i])>-eps)t=(t+1)%top;
        while((sta[i+1]-sta[i])/(sta[r+1]-sta[i])-(sta[i+1]-sta[i])/(sta[r]-sta[i])>-eps)r=(r+1)%top;
        if(i==0)l=r;
        while((sta[i+1]-sta[i])/(sta[l]-sta[i])-(sta[i+1]-sta[i])/(sta[l+1]-sta[i])>-eps)l=(l+1)%top;
        ll=(sta[i+1]-sta[i])/(sta[l]-sta[i])/ds;
        rr=(sta[i+1]-sta[i])/(sta[r]-sta[i])/ds;
        h=(sta[i+1]-sta[i])*(sta[t]-sta[i])/ds;
        if(mn>(rr-ll)*h){
            mn=(rr-ll)*h;
            ans[0]=sta[i]+(sta[i+1]-sta[i])*(rr/ds);
            ans[1]=ans[0]+(sta[r]-ans[0])*(h/dis(sta[r],ans[0]));
            ans[2]=ans[1]+(sta[t]-ans[1])*((rr-ll)/dis(sta[t],ans[1]));
            ans[3]=ans[2]+(ans[0]-ans[1]);
        }
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)scanf("%lf%lf",&poi[i].x,&poi[i].y);
    sort(poi+1,poi+n+1,cmp);
    sta[++top]=poi[1];sta[++top]=poi[2];
    for(int i=3;i<=n;++i){
        while((poi[i]-sta[top-1])*(sta[top]-sta[top-1])>-eps&&top>=2)top--;
        sta[++top]=poi[i];
    }
    sort(poi+1,poi+n+1,cm2);
    int sa=top;
    if(sta[top]==poi[1])sta[++top]=poi[2],sa--;
    else sta[++top]=poi[1],sta[++top]=poi[2];
    for(int i=3;i<=n;++i){
        while((poi[i]-sta[top-1])*(sta[top]-sta[top-1])>-eps&&top>sa)top--;
        sta[++top]=poi[i];
    }
    top--;
    solve();
    printf("%.5lf\n",mn);
    int fir=0;
    for(int i=1;i<=3;++i)if(ans[fir]>ans[i])fir=i;
    for(int i=0;i<=3;++i)printf("%.5lf %.5lf\n",ans[(fir+i)%4],ans[(fir+i)%4]);
    return 0;
}
posted @ 2017-12-28 17:17  减维  阅读(181)  评论(0编辑  收藏  举报