关闭

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

197人阅读 评论(0) 收藏 举报
分类:

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

感天动地

一年前的代码真丑


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
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

BZOJ 1185 [HNOI2007]最小矩形覆盖 旋转卡壳

BZOJ 1185 [HNOI2007]最小矩形覆盖 旋转卡壳
  • wzq_QwQ
  • wzq_QwQ
  • 2015-09-09 18:23
  • 1400

bzoj1185: [HNOI2007]最小矩形覆盖 计算几何 旋转卡壳

又被卡精度。。。这概率绝了!!! 我们可以肯定凸包的一边肯定在矩形上,所以我们直接寻找上,左,右三个顶点就可以了。#include #include #include #include #in...
  • IED98
  • IED98
  • 2015-02-26 16:18
  • 586

bzoj 1185 [HNOI2007]最小矩形覆盖(坑)

旋转卡壳
  • chai_jing
  • chai_jing
  • 2017-05-30 21:27
  • 95

【BZOJ1185】最小矩形覆盖 计算几何 凸包 旋转卡壳

写完程序两小时,调对精度一小时hhh 首先不严格的直觉告诉我们所求矩形一定有一条边在凸包上,我们遍历凸包上的边,用类似旋转卡壳的方式得到凸包上的三个点,分别是在边上投影最靠前的点,在边上投影最靠后的点...
  • qq_34637390
  • qq_34637390
  • 2016-04-15 22:08
  • 296

【BZOJ 1185】[HNOI2007]最小矩形覆盖 旋转卡壳

不说了,待我吐完这口老血。。。。 一开始我看题目说配spj以为就可以随便输出4个点的位置,然而....spj居然只是用来判-0.00000的,调了一下午,最后改成输出最下面的顶点然后逆时针输出就过了,...
  • pbihao
  • pbihao
  • 2017-02-04 21:27
  • 128

bzoj 1185: [HNOI2007]最小矩形覆盖 旋转卡壳

先求出凸包,显然至少需要有一条边在凸包上(我只会感性理解不会证明QAQ),那么旋转卡壳一下就好了。 AC代码如下: #include #include #include #include #inclu...
  • lych_cys
  • lych_cys
  • 2016-04-14 10:21
  • 428

bzoj 1185: [HNOI2007]最小矩形覆盖 (旋转卡壳)

1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge Submit: 1406  So...
  • clover_hxy
  • clover_hxy
  • 2017-01-05 09:44
  • 105

BZOJ 1185 HNOI2007 最小矩形覆盖 旋转卡壳

题目大意:最小矩形覆盖 首先有一个结论:凸包上一定有一条边与矩形的一条边重合 证明:如果不存在一条边与矩形的一条边重合,那么我将这个矩形旋转一下一定会比之前更小 于是我们枚举其中一条边,对其余三...
  • PoPoQQQ
  • PoPoQQQ
  • 2015-01-23 15:20
  • 1389

旋转卡壳——凸多边形最小面积外接矩形

出处:http://blog.csdn.net/acmaker/article/details/3188123 凸多边形最小面积外接矩形 给定一个凸多边形 P , 面积最小的能装下 P (...
  • GeiZuoZuoZuo
  • GeiZuoZuoZuo
  • 2013-05-31 11:42
  • 1618

hdu 5251 矩形面积 (旋转卡壳求最小面积外接矩形)

矩形面积 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Sub...
  • clover_hxy
  • clover_hxy
  • 2017-01-04 21:18
  • 566
    个人资料
    • 访问:335100次
    • 积分:12687
    • 等级:
    • 排名:第1281名
    • 原创:972篇
    • 转载:3篇
    • 译文:0篇
    • 评论:54条
    最新评论