zoukankan      html  css  js  c++  java
  • P3187 [HNOI2007]最小矩形覆盖

    题意

    考虑矩形必定满足一条边和凸包重合(意会),于是我们枚举凸包的每一条边,考虑维护据该条边的最远点(p)、最左点(l)、最右点(r),这三个都可以旋转卡壳。

    首先最远点是经典的求凸包直径问题,我们移动时比较当前和下一个三角形的大小即可。

    之后考虑最左点和最右点,我们用点积求出投影长度来比较就好了。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=50010;
    const double eps=1e-12;
    const double inf=1e9;
    int n,m;
    double ans=inf;
    struct Point
    {
        double x,y;
        inline double len(){return sqrt(x*x+y*y);}
        Point operator+(const Point a)const{return (Point){x+a.x,y+a.y};}
        Point operator-(const Point a)const{return (Point){x-a.x,y-a.y};}
        Point operator*(const double k){return (Point){x*k,y*k};}
        Point operator/(const double k){return (Point){x/k,y/k};}
        double operator*(const Point a)const{return x*a.y-y*a.x;}
        double operator&(const Point a)const{return x*a.x+y*a.y;}
    }p[maxn],sta[maxn],ansp[5];
    inline int dcmp(double x)
    {
    	if(fabs(x)<=eps)return 0;
    	return x<0?-1:1;
    }
    inline bool cmp1(Point a,Point b){return !dcmp(a.y-b.y)?dcmp(a.x-b.x)<0:dcmp(a.y-b.y)<0;}
    inline bool cmp2(Point a,Point b)
    {
    	if(!dcmp(a.x)&&!dcmp(a.y))return 1;
    	else if(!dcmp(b.x)&&!dcmp(b.y))return 0;
    	else return atan2(a.y,a.x)<atan2(b.y,b.x);
    }
    inline Point get(Point a,Point b){return b-a;}
    inline void build()
    {
    	sort(p+1,p+n+1,cmp1);
    	for(int i=1;i<=n;i++)
    	{
    		while(m>1&&dcmp(get(sta[m-1],sta[m])*get(sta[m],p[i]))<=0)m--;
    		sta[++m]=p[i];
    	}
    	int tmp=m;
    	for(int i=n-1;i;i--)
    	{
    		while(m>tmp&&dcmp(get(sta[m-1],sta[m])*get(sta[m],p[i]))<=0)m--;
    		sta[++m]=p[i];
    	}
    	m--;sta[0]=sta[m];
    }
    inline void solve()
    {
    	int l=1,r=1,p=1;
    	double L=0,R=0,H=0;
    	for(int i=0;i<m;i++)
    	{
    		while(dcmp(get(sta[i],sta[i+1])*get(sta[i],sta[p+1])-get(sta[i],sta[i+1])*get(sta[i],sta[p]))>=0)p=(p+1)%m;
    		while(dcmp((get(sta[i],sta[i+1])&get(sta[i],sta[r+1]))-(get(sta[i],sta[i+1])&get(sta[i],sta[r]))>=0))r=(r+1)%m;
    		if(!i)l=r;
    		while(dcmp((get(sta[i],sta[i+1])&get(sta[i],sta[l+1]))-(get(sta[i],sta[i+1])&get(sta[i],sta[l]))<=0))l=(l+1)%m;
    		double d=get(sta[i],sta[i+1]).len();
    		L=(get(sta[i],sta[i+1])&get(sta[i],sta[l]))/d;
    		R=(get(sta[i],sta[i+1])&get(sta[i],sta[r]))/d;
    		H=fabs(get(sta[i],sta[i+1])*get(sta[i],sta[p])/d);
    		double tmp=H*(R-L);
    		if(tmp<ans)
    		{
    			ans=tmp;
    			ansp[1]=sta[i]+get(sta[i],sta[i+1])*(R/d);
    			ansp[2]=ansp[1]+get(ansp[1],sta[r])*(H/get(ansp[1],sta[r]).len());
    			ansp[3]=ansp[2]+get(ansp[1],sta[i])*((R-L)/get(ansp[1],sta[i]).len());
    			ansp[4]=ansp[1]+get(ansp[1],sta[i])*((R-L)/get(ansp[1],sta[i]).len());
    		}
    	}
    }
    int main()
    {
    	//freopen("test.in","r",stdin);
    	//freopen("test.out","w",stdout);
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
    	build();solve();
    	printf("%.5lf
    ",ans+eps);
    	sort(ansp+1,ansp+4+1,cmp2);
    	for(int i=1;i<=4;i++)printf("%.5lf %.5lf
    ",ansp[i].x+eps,ansp[i].y+eps);
    	return 0;
    }
    
  • 相关阅读:
    .NET备份博客园随笔分类文章
    部署到IIS报错:HTTP错误500.19,错误代码0x80070021
    部署到IIS报错:HTTP错误500.19,错误代码0x800700d
    css布局
    将Windows系统编译的.NET Core程序发布到Ubuntu系统
    在Ubuntu搭建.NET Core环境
    在Windows系统搭建.NET Core环境并创建运行ASP.NET网站
    2017-2018-2 1723《程序设计与数据结构》助教总结
    2017-2018-2 1723《程序设计与数据结构》实验四 & 实验五 & 课程总结 总结
    2017-2018-2 1723《程序设计与数据结构》第十一周作业 & 实验三 & (总体)第三周结对编程 总结
  • 原文地址:https://www.cnblogs.com/nofind/p/12212531.html
Copyright © 2011-2022 走看看