hdu 2823 The widest road (旋转卡壳求两凸包的最近距离)

The widest road

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1454    Accepted Submission(s): 273


Problem Description
There were two families in the village — family A and family B, while these two families didn’t get along well with each other. Now the head of the village decided to make a road through the village and it must be straight, for a straight line makes the way shortest and meanwhile, saves the cost. At that time, the heads of the two families proposed, because they didn’t want their own families live separated along the two sides of the road, thus it might decrease the solidarity of family. Besides, the two families were antipathetic to each other; neither wanted to live together with the other in a same side of the road. Then it made the village head in a pickle, he hoped the road to be as wide as possible. So what’s the possible maximal width of this road?
In order to simplify the problem, let’s regard the living place of each family member is just a point.
 

Input
There are several test cases in the input.

The first line of each input contains n and m (1 ≤ m,n ≤ 1000). As for the following n lines, there are two numbers in every line, representing the living places of A family members. And the following m lines represent the living places of B family members.
 

Output
The output numbers of each line are the maximal width of the road (retain four decimal), while if it’s impossible to make such a road, then just output 0.0000.
 

Sample Input
 
   
3 3 0.0 0.0 1.0 0.0 0.0 1.0 4.0 0.0 5.0 0.0 4.0 1.0
 

Sample Output
 
   
3.0000
 

Source
2009 Multi-University Training Contest 1 - Host by TJU
 

Recommend
gaojie   |   We have carefully selected several similar problems for you:   2825  2824  2820  2819  2818 
 

Statistic |  Submit |  Discuss | Note

题目大意:给出两个点集,求出两个凸包后,求两个凸包的最近距离。需要特判两个凸包内含和相交各种乱七八糟的情况。

题解:旋转卡壳求两凸包的最近距离

考虑如下的算法, 算法的输入是两个分别有m和n个顺时针给定顶点的凸多边形P和Q。

1.计算P上y坐标值最小的顶点(称为 yminP )和Q上y坐标值最大的顶点(称为 ymaxQ)。

2.为多边形在 yminP 和 ymaxQ 处构造两条切线 LP 和 LQ 使得他们对应的多边形位于他们的右侧。

  此时 LP 和 LQ 拥有不同的方向, 并且 yminP 和 ymaxQ 成为了多边形间的一个对踵点对。

3.计算距离(yminP,ymaxQ) 并且将其维护为当前最小值。

4.顺时针同时旋转平行线直到其中一个与其所在的多边形的边重合。

5.如果只有一条线与边重合, 那么只需要计算“顶点-边”对踵点对和“顶点-顶点”对踵点对距离。 都将他们与当前最小值

比较, 如果小于当前最小值则进行替换更新。如果两条切线都与边重合,那么情况就更加复杂了。如果边“交叠”,也就是

可以构造一条与两条边都相交的公垂线(但不是在顶点处相交), 那么就计算“边-边”距离。 否则计算三个新的“顶点-顶

点”对踵点对距离。 所有的这些距离都与当前最小值进行比较, 若小于当前最小值则更新替换。

6.重复执行步骤4和步骤5, 直到新的点对为(yminP,ymaxQ)。

7.输出最小距离。


#include
#include
#include
#include
#include
#define N 1003
#define eps 1e-8
using namespace std;
struct vector {
	double x,y;
	vector (double X=0,double Y=0){
		x=X,y=Y;
	}
}p[N],q[N],ch[N];
double ans;
int n,m;
typedef vector point;
vector operator -(vector a,vector b){return vector (a.x-b.x,a.y-b.y);}
vector operator +(vector a,vector b){return vector (a.x+b.x,a.y+b.y);}
vector operator *(vector a,double t){return vector (a.x*t,a.y*t);}
vector operator /(vector a,double t){return vector (a.x/t,a.y/t);}
bool operator <(vector a,vector b)
{
	return a.x0) return len(v3);
	return fabs(cross(v1,v2))/len(v1);
}
double distl(point p,point a,point b)
{
	vector v=p-a; vector u=b-a;
	return fabs(cross(v,u))/len(u);
}
void convexhull(point *a,int &n)
{
    sort(a,a+n);
    int cnt=0;
    if (n==1) {
    	ch[cnt++]=a[0];
    	n=cnt;
    	for (int i=0;i1&&cross(ch[cnt-1]-ch[cnt-2],a[i]-ch[cnt-2])<=0) cnt--;
		ch[cnt++]=a[i];
	}
	int k=cnt;
	for (int i=n-2;i>=0;i--){
		while (cnt>k&&cross(ch[cnt-1]-ch[cnt-2],a[i]-ch[cnt-2])<=0) cnt--;
		ch[cnt++]=a[i]; 
	}
	cnt--;
	n=cnt;
	for (int i=0;iq[y].y)?i:y;
	for (int i=0;i=0) t++;
	if (t==n) return true;
	else return false;
}
bool check()
{
	for (int i=0;im) swap(n,m),swap(p,q);
		if (n==1) {
			if (m==1) ans=len(p[0]-q[0]);
			else {
				if (m==2) ans=dists(p[0],q[0],q[1]);
				else {
				 if (pointin(p[0],q,m)) ans=0.0000;
				 else for (int i=0;i



你可能感兴趣的:(计算几何)