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\n",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\n",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\n",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\n",q[s].x,q[s].y);
	}return 0;
}
posted @ 2018-11-23 20:39  bztMinamoto  阅读(205)  评论(0编辑  收藏  举报
Live2D