zoukankan      html  css  js  c++  java
  • UVA 12307 Smallest Enclosing Rectangle

    https://vjudge.net/problem/UVA-12307

    题目

    给一些点,求包含这些点的面积最小的和周长最小的长方形的面积。

    题解

    显然,包含这些点就是包含这些点的凸包,然后可以证明满足周长或面积最小的长方形一定过凸包的一条边。

    不会直接证明= =可以用反证法

    如果不过任意一条边,那么多边形与长方形就有三种关系:有2、3、4个点在长方形上

     

    设其中的边长为已知,通过角度关系,可以证明长$AD$和宽$AB$的和(配角公式)与积(积化和差)与夹角成单峰函数,夹角范围是$[0,frac{pi}{2}]$,于是一定过一条边时取最小

    参考一个求解多边形最小面积外接矩形的算法 - 图文 - 百度文库

    于是可以参考旋转卡壳,选出到一条边距离最长的点,最左边的点和最右边的点,并且边旋转时,这些点也会跟着旋转,于是可以降到$O(n)$

    加上凸包$O(nlog n)$

    AC代码

    #include<cstdio>
    #include<cmath>
    #include<cctype>
    #include<map>
    #include<algorithm>
    #include<vector>
    #include<cstring>
    using namespace std;
    
    #define REP(i,a,b) for(register int i=(a); i<(b); i++)
    #define REPE(i,a,b) for(register int i=(a); i<=(b); i++)
    #define PERE(i,a,b) for(register int i=(a); i>=(b); i--)
    
    #ifdef sahdsg
    #define DBG(...) printf(__VA_ARGS__),fflush(stdout)
    #else
    #define DBG(...) (void)0
    #endif
    
    template<class T>
    inline void read(T&x) {
    	static int si; static char ch;
    	x=0,si=1; do ch=getchar(); while(!isdigit(ch)&&ch!='-');if(ch=='-') si=-1, ch=getchar(); while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}x*=si;
    }
    template<class T, class...A> inline void read(T&t,A&...a){read(t); read(a...);}
    #define D Point
    #define CD const Point
    template<class T,int Z> struct Arr {
    	T data[Z];int n;
    	inline T& operator[](int a) {return data[a];}
    	inline void push(const T&x) {data[n++]=x;}
    	inline void pop() {n--;}
    };
    
    #define EPS 1e-9
    inline int dcmp(double x) {return fabs(x)<EPS?0:(x<0?-1:1);}
    
    struct Point {
    	double x,y;
    	};
    	bool operator<(CD&l, CD&r) {return dcmp(l.x-r.x)<0 || (dcmp(l.x-r.x)==0 && dcmp(l.y-r.y)<0);}
    	bool operator==(CD&l, CD&r) {return dcmp(l.x-r.x)==0 && dcmp(l.y-r.y)==0;}
    	D operator+(CD&l, CD&r) {return (D){l.x+r.x,l.y+r.y};}
    	D operator-(CD&l, CD&r) {return (D){l.x-r.x,l.y-r.y};}
    	D operator/(CD&l, double a) {return (D){l.x/a,l.y/a};}
    	D operator*(CD&l, double a) {return (D){l.x*a,l.y*a};}
    	D operator*(double a, CD&l)  {return (D){l.x*a,l.y*a};}
    	double dot(CD&l, CD&r) {return l.x*r.x+l.y*r.y;}
    	double cross(CD&l, CD&r) {return l.x*r.y-l.y*r.x;}
    	double len(CD&l) {return sqrt(l.x*l.x+l.y*l.y);}
    
    #undef D
    #undef CD
    
    #define MAXN 100007
    typedef Arr<Point,MAXN> Plg;
    
    void convex(Plg&p, Plg &ch) {
    	sort(p.data,p.data+p.n);
    	int &m=ch.n; m=0;
    	REP(i,0,p.n) { while(m>1 && cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;ch[m++]=p[i];}
    	int k=m;
    	PERE(i,p.n-2,0) {while(m>k && cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;ch[m++]=p[i];}
    	if(p.n>1) m--;
    }
    
    double area(Plg&p) {
    	double ans=0;
    	REP(i,0,p.n) {
    		ans+=cross(p[i],p[(i+1)%p.n]);
    	}
    	return ans;
    }
    
    Plg a,b;
    
    int main() {
    	int n;
    	while(~scanf("%d", &n) && n) {
    		REP(i,0,n) {
    			scanf("%lf%lf", &a[i].x, &a[i].y);
    		}
    		a.n=n; convex(a,b);
    		double S=2e33,L=2e33;
    		b[b.n]=b[0]; int v=1; int lm, rm=0; bool fi=false;
    		REP(u,0,b.n) {
    			while(1) {
    				double dt=cross(b[u+1]-b[u],b[v+1]-b[v]);
    				if(dt<=0) {
    					break;
    				}
    				v++;
    				if(v>=b.n) v=0;
    			}
    			if(!fi) fi=true,lm=v;
    			while(1) {
    				double ds=dot(b[u+1]-b[u],b[lm+1]-b[lm]);
    				if(ds>=0) break;
    				lm++;
    				if(lm>=b.n) lm=0;
    			}
    			while(1) {
    				double ds=dot(b[u+1]-b[u],b[rm+1]-b[rm]);
    				if(ds<=0) break;
    				rm=(rm+1)%b.n;
    				if(rm>=b.n) rm=0;
    			}
    			double z=len(b[u+1]-b[u]);
    			double l=dot(b[u+1]-b[u],b[rm]-b[lm])/z;
    			double h=cross(b[u+1]-b[u],b[v]-b[u])/z;
    			S=min(S,l*h);
    			L=min(L,(l+h)*2);
    		}
    		printf("%.2lf %.2lf
    ",S,L);
    	}
    }
    
  • 相关阅读:
    Silverlight & Blend动画设计系列三:缩放动画(ScaleTransform) from http://www.cnblogs.com/beniao/archive/2010/03/26/1694157.html
    基于知识库的信息推荐系统
    观察者模式之:一个游戏设想
    Expression Blend制作画卷效果 from http://www.cnblogs.com/alexis/archive/2010/12/23/1915402.html
    为了忘却的生活
    C 文件读写
    VC++中,CString,in,char,等数据类型的相互转化 from:http://blog.csdn.net/heaven13483/article/details/7553176
    【ML2】最小二乘法(least squares)介绍
    机器学习的基本概念
    【ML95】SVM的sklearn.svm.SVC()函数应用
  • 原文地址:https://www.cnblogs.com/sahdsg/p/11618093.html
Copyright © 2011-2022 走看看