码迷,mamicode.com
首页 > 其他好文 > 详细

【旋转卡壳】poj3608 Bridge Across Islands

时间:2017-02-02 19:08:11      阅读:217      评论:0      收藏:0      [点我收藏+]

标签:while   clu   can   ble   最大的   sla   int   叉积   ace   

给你俩凸包,问你它们的最短距离。

咋做就不讲了,经典题,网上一片题解。

把凸包上的点逆时针排序。可以取它们的平均点,然后作极角排序。

旋转卡壳其实是个很模板化的东西……

先初始化分别在凸包P和Q上取哪个点,一般在P上取纵坐标最小的点,在Q上取纵坐标最大的点

for i=1 to n(n是凸包P上的点数)

{

while(两条边的叉积>0)

  {

  凸包Q上的点++

  }

计算当前两条边之间的答案(或者说每条边的2个端点到另一条边的答案)

凸包P上的点++

}

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define EPS 0.0000000001
struct Point
{
	double x,y;
	Point(){}
	Point(const double &X,const double &Y)
	  {
	  	x=X;
	  	y=Y;
	  }
	double Length()
	  {
	  	return sqrt(x*x+y*y);
	  }
}p[2][10010],bao[2][10010],ave;
typedef Point Vector;
Vector operator - (const Point &a,const Point &b)
{
	return Vector(a.x-b.x,a.y-b.y);
}
bool cmp (const Point &a,const Point &b)
{
	return atan2((a-ave).y,(a-ave).x)<atan2((b-ave).y,(b-ave).x);
}
double Cross(const Vector &a,const Vector &b)
{
	return a.x*b.y-a.y*b.x;
}
double Dot(const Vector &a,const Vector &b)
{
	return a.x*b.x+a.y*b.y;
}
double calc(Point P,Point A,Point B)
{
	Vector v1=B-A,v2=P-A,v3=P-B;
	if(Dot(v1,v2)<EPS) return v2.Length();
	else if(Dot(v1,v3)>(-EPS)) return v3.Length();
	else return fabs(Cross(v1,v2))/v1.Length();
}
int n,m;
int main()
{
	//freopen("y.in","r",stdin);
	while(1)
	  {
	  	scanf("%d%d",&n,&m);
	  	if(n==0 && m==0)
	  	  break;
	  	for(int i=0;i<n;++i)
	  	  {
	  	  	scanf("%lf%lf",&p[0][i].x,&p[0][i].y);
	  	  	ave.x+=p[0][i].x;
	  	  	ave.y+=p[0][i].y;
	  	  }
	  	ave.x/=(double)n;
	  	ave.y/=(double)n;
	  	for(int i=0;i<m;++i)
	  	  scanf("%lf%lf",&p[1][i].x,&p[1][i].y);
		sort(p[0],p[0]+n,cmp);
		ave.x=ave.y=0;
		for(int i=0;i<m;++i)
		  {
		  	ave.x+=p[1][i].x;
	  	  	ave.y+=p[1][i].y;
		  }
	  	ave.x/=(double)m;
	  	ave.y/=(double)m;
		sort(p[1],p[1]+m,cmp);
	  	int nowP=0,nowQ=0;
	  	for(int i=1;i<n;++i)
	  	  if(p[0][i].y-p[0][nowP].y<(-EPS))
	  	    nowP=i;
	  	for(int i=1;i<m;++i)
	  	  if(p[1][i].y-p[1][nowQ].y>EPS)
	  	    nowQ=i;
	  	double ans=1000000000000000007.0;
	  	for(int i=0;i<n;++i)
		  {
			while(Cross(p[1][(nowQ+1)%m]-p[1][nowQ],p[0][nowP]-p[0][(nowP+1)%n])>EPS)
			  nowQ=(nowQ+1)%m;
			ans=min(ans,
			min(calc(p[0][nowP],p[1][nowQ],p[1][(nowQ+1)%m]),
			min(calc(p[0][(nowP+1)%n],p[1][nowQ],p[1][(nowQ+1)%m]),
			min(calc(p[1][nowQ],p[0][nowP],p[0][(nowP+1)%n]),
			calc(p[1][(nowQ+1)%m],p[0][nowP],p[0][(nowP+1)%n])))));
			nowP=(nowP+1)%n;
		  }
		printf("%.5lf\n",ans);
	  }
	return 0;
}

【旋转卡壳】poj3608 Bridge Across Islands

标签:while   clu   can   ble   最大的   sla   int   叉积   ace   

原文地址:http://www.cnblogs.com/autsky-jadek/p/6361473.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!