zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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
    ",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
    ",q[s].x,q[s].y);
    	}return 0;
    }
    
  • 相关阅读:
    django DEBUG=False
    Lftp 简单使用步骤
    django admin管理后台中文添加问题
    Rsync同步设置的一例
    在nginx中,禁止IP访问.只可以使用域名访问.
    python imaplib无痕取信的主要
    Centos安装配置Postfix邮件服务器--网址
    还没有写完准备弡上cpickle 还有字典
    python 截取某一天的日志,简单操作
    abp 关闭审计日志
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10009640.html
Copyright © 2011-2022 走看看