zoukankan      html  css  js  c++  java
  • 【BZOJ1185】【HNOI2007】最小矩形覆盖(凸包+旋转卡壳)

    传送门

    题意:求最小矩阵覆盖

    有这样一个结论:矩阵一定有一条边在凸包上(不会证)

    那可以枚举每条边
    同时旋转卡壳
    只是这时不只维护一个对踵点对,同时在左右侧再维护一个最远点
    可以发现左右最远点一定是和当前边点积最小/最大的
    不断统计答案就是了

    注意printfprintf遇到0.0000.000会输出0.0000-0.0000,要特判一下

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
    	return res*f;
    }
    const int N=50005;
    const double pi=acos(-1);
    const double eps=1e-8;
    struct point{
    	double x,y;
    	point(double a=0,double b=0){
    		x=a,y=b;
    	}
    	friend inline point operator +(const point &a,const point &b){
    		return point(a.x+b.x,a.y+b.y);
    	}
    	friend inline point operator -(const point &a,const point &b){
    		return point(a.x-b.x,a.y-b.y);
    	}
    	friend inline double operator *(const point &a,const point &b){
    		return (a.x*b.y-a.y*b.x);
    	}
    	friend inline point operator *(const point &a,const double &b){
    		return point(a.x*b,a.y*b);
    	}
    	friend inline double operator /(const point &a,const point &b){
    		return a.x*b.x+a.y*b.y;
    	}
    	inline double calc(){
    		return sqrt(x*x+y*y);
    	}
    }p[N],q[N],t[5];
    inline bool comp(const point &a,const point &b){
    	double res=(a-p[1])*(b-p[1]);
    	return (res==0)?((a-p[1]).calc()<(b-p[1]).calc()):(res>0);
    }
    int n,top;
    double ans=1e9;
    inline void graham(){
    	int idx=1;
    	for(int i=2;i<=n;i++){
    		if(p[idx].y>p[i].y||(p[idx].y==p[i].y&&p[i].x<p[idx].x))
    		idx=i;
    	}
    	if(idx!=1)swap(p[idx],p[1]);
    	sort(p+2,p+n+1,comp);
    	q[++top]=p[1];
    	for(int i=2;i<=n;++i){
    		while(top>=3&&((p[i]-q[top-1])*(q[top]-q[top-1])>=0))
    			top--;
    		q[++top]=p[i];
    	}
    	q[0]=q[top];
    }
    inline void solve(){
    	int l=1,r=1,h=1;
    	for(int i=0;i<top;i++){
    		double dis=(q[i]-q[i+1]).calc();
    		while((q[i+1]-q[i])*(q[h+1]-q[i])-(q[i+1]-q[i])*(q[h]-q[i])>-eps)h=(h+1)%top;
    		while((q[i+1]-q[i])/(q[r+1]-q[i])-(q[i+1]-q[i])/(q[r]-q[i])>-eps)r=(r+1)%top;
    		if(i==0)l=r;
    		while((q[i+1]-q[i])/(q[l+1]-q[i])-(q[i+1]-q[i])/(q[l]-q[i])<eps)l=(l+1)%top;
    	    double lg=(q[i+1]-q[i])/(q[l]-q[i])/dis,rg=(q[i+1]-q[i])/(q[r]-q[i])/dis;
    		double ht=(q[i+1]-q[i])*(q[h]-q[i])/dis;
    		if(ht<0)ht=-ht;
    		if((rg-lg)*ht<ans){
    			ans=(rg-lg)*ht;
    			t[0]=q[i]+(q[i+1]-q[i])*(rg/dis);
    			t[1]=t[0]+(q[r]-t[0])*(ht/(q[r]-t[0]).calc());
    			t[2]=t[1]+(q[i]-t[0])*((rg-lg)/(q[i]-t[0]).calc());
    			t[3]=t[2]+(t[0]-t[1]);
    		}
    	}
    }
    int main(){
    	n=read();
    	for(int i=1;i<=n;i++){
    		scanf("%lf%lf",&p[i].x,&p[i].y);
    	}
    	graham();
    	solve();
    	if(ans<eps)cout<<"0.00000
    ";
    	else printf("%.5lf
    ",ans);
    	int d=0;
    	for(int i=1;i<=3;i++){
    		if(t[i].y<t[d].y||(t[i].y==t[d].y&&t[i].x<t[d].x))
    		d=i;
    	}
    	for(int i=0;i<=3;i++){
    		if(t[(i+d)%4].x<eps)cout<<"0.00000 ";
    		else printf("%.5lf ",t[(i+d)%4].x);
    		if(t[(i+d)%4].y<eps)cout<<"0.00000
    ";
    		else printf("%.5lf
    ",t[(i+d)%4].y);
    	}
    }
    
  • 相关阅读:
    MyEclipse中配置Hibernate
    struts2_对Map进行双层迭代
    Hibernate关联关系全集
    CodeIgniter+Smarty配置
    去掉php框架CI默认url中的index.php【整理】
    jquery的show方法是display:block还是display:inline呢?
    Codeigniter中的Error【转】
    去除 inlineblock 空隙终极解决方案
    jquery三级折叠菜单
    css实现页面文字不换行、自动换行、强制换行
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145656.html
Copyright © 2011-2022 走看看