[旋转卡壳] BZOJ 1185 [HNOI2007]最小矩形覆盖 && 2218 Uva10173 Smallest Bounding Rectangle

感动死了 一年前卡精度 今天搞搞搞就过了

感天动地

一年前的代码真丑


1185

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
#define eps 1e-6
using namespace std;
typedef long double ld;

inline int dcmp(ld a,ld b)
{
	if (fabs(a-b)<eps) return 0;
	if (a<b) return -1; return 1;
}

struct Point{
	ld x,y;
	Point(ld x=0,ld y=0):x(x),y(y) { }
	bool operator < (const Point &b) const{
		return dcmp(x,b.x)<0 || (dcmp(x,b.x)==0 && dcmp(y,b.y)<0);
	}
}P[50005],H[50005];
ld s[50005];

int n,cnt;

inline ld Dot(Point p1,Point p2,Point p0)
{
	return (p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);
}

inline ld Cross(Point p1,Point p2,Point p0)
{
	return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}

inline ld Dist(Point p1,Point p2)
{
	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}

inline ld Dist(Point p1,Point p2,Point p0)
{
	return fabs(Cross(p1,p2,p0)/Dist(p1,p2));
}

inline ld Area(Point p1,Point p2,Point p0)
{
	return fabs(Cross(p1,p2,p0))/2;
}

inline void Qhull(int l,int r,Point a,Point b)
{
	int i=l-1,j=r+1,x=l;
	for (int k=l;k<=r;k++)
		if (dcmp(s[k],s[x])>0 || (dcmp(s[x],s[k])==0 && P[x]<P[k]))
			x=k;
	Point y=P[x];
	for (int k=l;k<=r;k++)
	{
		s[++i]=Cross(P[k],a,y);
		if (dcmp(s[i],0)>0) swap(P[k],P[i]); else s[i--]=0;
	}
	for (int k=r;k>=l;k--)
	{
		s[--j]=Cross(P[k],y,b);
		if (dcmp(s[j],0)>0) swap(P[k],P[j]); else s[j++]=0;
	}
	if (l<=i) Qhull(l,i,a,y);
	H[++cnt]=y;
	if (j<=r) Qhull(j,r,y,b);
}

Point AP[5];

inline bool cmp(Point a,Point b)
{
	return a.x*b.y-b.x*a.y>0;
}

inline void Sort()
{
	int k=1;
	for (int i=2;i<=4;i++)
		if (AP[i].y<AP[k].y || (AP[i].y==AP[k].y && AP[i].x<AP[k].y))
			k=i;
	swap(AP[1],AP[k]);
	sort(AP+2,AP+5,cmp);
}

struct Line{
	ld k,b;
	ld x;
};

inline Point Cha(Line a,Line b)
{
	if (a.k<-1e100 && a.b>1e100)
		return Point(a.x,b.k*a.x+b.b);
	if (b.k<-1e100 && b.b>1e100)
		return Point(b.x,a.k*b.x+a.b);	 
	ld x=(b.b-a.b)/(a.k-b.k);
	return Point(x,a.k*x+a.b);
}

inline void Get(Point A,Point B,Point C,Point D,Point E)
{
	Line Li1,Li2,Li3,Li4;
	if (dcmp(A.x,B.x))
		Li1.k=(B.y-A.y)/(B.x-A.x),Li1.b=A.y-A.x*Li1.k;
	else
		Li1.k=-1e130,Li1.b=1e130,Li1.x=A.x;
	if (dcmp(Li1.k,0))
	{
		Li2.k=-1/Li1.k;
		Li2.k=dcmp(Li2.k,0)?Li2.k:0.0;
		Li2.b=C.y-C.x*Li2.k;
	}
	else
		Li2.k=-1e130,Li2.b=1e130,Li2.x=C.x;
	if (dcmp(Li1.k,0))
		Li3.k=-1/Li1.k,Li3.k=dcmp(Li3.k,0)?Li3.k:0.0,Li3.b=D.y-D.x*Li3.k;
	else
		Li3.k=-1e130,Li3.b=1e130,Li3.x=D.x;
	if (fabs(Li1.k)<1e100)
		Li4.k=Li1.k,Li4.b=E.y-E.x*Li4.k;
	else
		Li4=Li1,Li4.x=E.x;
	AP[1]=Cha(Li1,Li2);
	AP[2]=Cha(Li1,Li3);
	AP[3]=Cha(Li4,Li2);
	AP[4]=Cha(Li4,Li3);
}

int main()
{
	ld ans,tmp,A,B; double xx,yy;
	Point X,Y,C,D;
	int L1,L2,L3;
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
		int x=1;
		scanf("%d",&n);
		for (int i=1;i<=n;i++)
		{
			scanf("%lf%lf",&xx,&yy);
			P[i].x=xx; P[i].y=yy;
			if (P[i]<P[x]) x=i;
		}
		if (n==3)
		{
			ld ret=1e20;
			if (dcmp(ret,Dist(P[1],P[2])*Dist(P[1],P[2],P[3]))<0)
				ret=Dist(P[1],P[2])*Dist(P[1],P[2],P[3]),Get(P[1],P[2],P[1],P[2],P[3]);
			if (dcmp(ret,Dist(P[2],P[3])*Dist(P[2],P[3],P[1]))<0)
				ret=Dist(P[2],P[3])*Dist(P[2],P[3],P[1]),Get(P[2],P[3],P[2],P[3],P[1]);
			if (dcmp(ret,Dist(P[1],P[3])*Dist(P[1],P[3],P[2]))<0)
				ret=Dist(P[1],P[3])*Dist(P[1],P[3],P[2]),Get(P[1],P[3],P[1],P[3],P[2]);
			Sort();
			printf("%.5lf\n",(double)ret);
			for (int i=1;i<=4;i++)
				printf("%.5lf %.5lf\n",(double)AP[i].x,(double)AP[i].y);
			return 0;
		}
		swap(P[1],P[x]);
		H[++cnt]=P[1];
		Qhull(2,n,P[1],P[1]);
		n=cnt;
		for (int i=1;i<=cnt;i++)
			P[i]=H[i];
		Y=H[n]; X=H[1];
		L1=2;
		for (int i=3;i<n;i++)
			if (dcmp(Dist(X,Y,P[i]),Dist(X,Y,P[L1]))>0)
				L1=i;
		L2=2;
		for (int i=3;i<n;i++)
			if (dcmp(Dot(Y,P[i],X)/Dist(X,Y),Dot(Y,P[L2],X)/Dist(X,Y))<0)
				L2=i;
		L3=2;
		for (int i=3;i<n;i++)
			if (dcmp(Dot(X,P[i],Y)/Dist(X,Y),Dot(X,P[L3],Y)/Dist(X,Y))<0)
				L3=i;
		B=Dist(X,Y,P[L1]);
		A=Dist(X,Y);
		C=X;
		tmp=Dot(Y,P[L2],X)/Dist(X,Y);
		if (dcmp(tmp,0.0)<0) A-=tmp,C=P[L2];
		D=Y;
		tmp=Dot(X,P[L3],Y)/Dist(X,Y);
		if (dcmp(tmp,0.0)<0) A-=tmp,D=P[L3];
		ans=A*B; Get(X,Y,C,D,P[L1]);
		for (int i=1;i<n;i++)
		{
			Y=P[i]; X=P[i+1];
			while (dcmp(Dist(X,Y,P[L1]),Dist(X,Y,P[L1%n+1]))<0) 
				L1=L1%n+1;
			while (dcmp(Dot(Y,P[L2%n+1],X)/Dist(X,Y),Dot(Y,P[L2],X)/Dist(X,Y))<0)
				L2=L2%n+1;
			while (dcmp(Dot(X,P[L3%n+1],Y)/Dist(X,Y),Dot(X,P[L3],Y)/Dist(X,Y))<0)
				L3=L3%n+1;
			B=Dist(X,Y,P[L1]);
			A=Dist(X,Y);
			C=X;
			tmp=Dot(Y,P[L2],X)/Dist(X,Y);
			if (dcmp(tmp,0.0)<0) A-=tmp,C=P[L2];
			D=Y;
			tmp=Dot(X,P[L3],Y)/Dist(X,Y);
			if (dcmp(tmp,0.0)<0) A-=tmp,D=P[L3];
			if (dcmp(ans,A*B)>0)
				ans=A*B,Get(X,Y,C,D,P[L1]);
		}
		Sort();
		printf("%.5lf\n",(double)ans);
		for (int i=1;i<=4;i++)
		{
			AP[i].x=dcmp(AP[i].x,0)?AP[i].x:0;
			AP[i].y=dcmp(AP[i].y,0)?AP[i].y:0;
			printf("%.5lf %.5lf\n",(double)AP[i].x,(double)AP[i].y);
		}
	return 0;
}


2218

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
#define eps 1e-6
using namespace std;
typedef long double ld;

inline int dcmp(ld a,ld b)
{
	if (fabs(a-b)<eps) return 0;
	if (a<b) return -1; return 1;
}

struct Point{
	ld x,y;
	bool operator < (const Point &b) const{
		return dcmp(x,b.x)<0 || (dcmp(x,b.x)==0 && dcmp(y,b.y)<0);
	}
}P[1005],H[1005];
ld s[1005];

int n,cnt;

inline ld Dot(Point p1,Point p2,Point p0)
{
	return (p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);
}

inline ld Cross(Point p1,Point p2,Point p0)
{
	return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}

inline ld Dist(Point p1,Point p2)
{
	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}

inline ld Dist(Point p1,Point p2,Point p0)
{
	return fabs(Cross(p1,p2,p0)/Dist(p1,p2));
}

inline ld Area(Point p1,Point p2,Point p0)
{
	return fabs(Cross(p1,p2,p0))/2;
}

inline void Qhull(int l,int r,Point a,Point b)
{
	int i=l-1,j=r+1,x=l;
	for (int k=l;k<=r;k++)
		if (dcmp(s[k],s[x])>0 || (dcmp(s[x],s[k])==0 && P[x]<P[k]))
			x=k;
	Point y=P[x];
	for (int k=l;k<=r;k++)
	{
		s[++i]=Cross(P[k],a,y);
		if (dcmp(s[i],0)>0) swap(P[k],P[i]); else s[i--]=0;
	}
	for (int k=r;k>=l;k--)
	{
		s[--j]=Cross(P[k],y,b);
		if (dcmp(s[j],0)>0) swap(P[k],P[j]); else s[j++]=0;
	}
	if (l<=i) Qhull(l,i,a,y);
	H[++cnt]=y;
	if (j<=r) Qhull(j,r,y,b);
}

int main()
{
	ld ans,tmp,A,B; double xx,yy;
	Point X,Y;
	int L1,L2,L3;
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	while (1)
	{
		int x=1;
		scanf("%d",&n); if (n==0) break;
		for (int i=1;i<=n;i++)
		{
			scanf("%lf%lf",&xx,&yy);
			P[i].x=xx; P[i].y=yy;
			if (P[i]<P[x]) x=i;
		}
		if (n<=3)
		{
			if (n==1 || n==2) 
				printf("%.4lf\n",0.0);
			else if (n==3)
			{
				ld ret=1e20;
				ret=min(ret,Dist(P[1],P[2])*Dist(P[1],P[2],P[3]));
				ret=min(ret,Dist(P[2],P[3])*Dist(P[2],P[3],P[1]));
				ret=min(ret,Dist(P[1],P[3])*Dist(P[1],P[3],P[2]));
				printf("%.4lf\n",(double)ret);
			}
			cl(P); cl(H); cnt=0; cl(s);
			continue;
		}
		swap(P[1],P[x]);
		H[++cnt]=P[1];
		Qhull(2,n,P[1],P[1]);
		n=cnt;
		for (int i=1;i<=cnt;i++)
			P[i]=H[i];
		Y=H[n]; X=H[1];
		L1=2;
		for (int i=3;i<n;i++)
			if (dcmp(Dist(X,Y,P[i]),Dist(X,Y,P[L1]))>0)
				L1=i;
		L2=2;
		for (int i=3;i<n;i++)
			if (dcmp(Dot(Y,P[i],X)/Dist(X,Y),Dot(Y,P[L2],X)/Dist(X,Y))<0)
				L2=i;
		L3=2;
		for (int i=3;i<n;i++)
			if (dcmp(Dot(X,P[i],Y)/Dist(X,Y),Dot(X,P[L3],Y)/Dist(X,Y))<0)
				L3=i;
		B=Dist(X,Y,P[L1]);
		A=Dist(X,Y);
		tmp=Dot(Y,P[L2],X)/Dist(X,Y);
		if (dcmp(tmp,0.0)<0) A-=tmp;
		tmp=Dot(X,P[L3],Y)/Dist(X,Y);
		if (dcmp(tmp,0.0)<0) A-=tmp;
		ans=A*B;
		for (int i=1;i<n;i++)
		{
			Y=P[i]; X=P[i+1];
			while (dcmp(Dist(X,Y,P[L1]),Dist(X,Y,P[L1%n+1]))<0) 
				L1=L1%n+1;
			while (dcmp(Dot(Y,P[L2%n+1],X)/Dist(X,Y),Dot(Y,P[L2],X)/Dist(X,Y))<0)
				L2=L2%n+1;
			while (dcmp(Dot(X,P[L3%n+1],Y)/Dist(X,Y),Dot(X,P[L3],Y)/Dist(X,Y))<0)
				L3=L3%n+1;
			B=Dist(X,Y,P[L1]);
			A=Dist(X,Y);
			tmp=Dot(Y,P[L2],X)/Dist(X,Y);
			if (dcmp(tmp,0.0)<0) A-=tmp;
			tmp=Dot(X,P[L3],Y)/Dist(X,Y);
			if (dcmp(tmp,0.0)<0) A-=tmp;
			ans=min(ans,A*B);
		}
		printf("%.4lf\n",(double)ans);
		cl(P); cl(H); cnt=0; cl(s);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值