旋转卡壳解poj3608Bridge Across Islands

继续上一次的旋转卡壳的问题,这次是求两个凸包的最短距离,

其实选择卡壳就是只要找到"当前向量面积不小于下一个向量面积"即可,

满足这个条件,当前的两个ymin和ymax点就是一对对踵点了。

代码如下,欢迎参考:

#include<cmath>
#include<cstdio>
#include<iostream>
using namespace std;
typedef struct{float x,y;} Dot;
Dot operator -(Dot a,Dot b){Dot c={a.x-b.x,a.y-b.y};return c;}
float operator *(Dot a,Dot b){return a.x*b.y-b.x*a.y;}
float operator /(Dot a,Dot b){return a.x*b.x+a.y*b.y;}//点积判断这个点是否在直线外
float dis(Dot a,Dot b){return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));}
float dtl(Dot a,Dot b,Dot c)//c点到线段ab的最短距离
{
	if((b-a)/(c-a)<0) return dis(c,a);
	if((a-b)/(c-b)<0) return dis(c,b);
	return fabs((a-b)*(c-b)/dis(a,b));
}
float ltl(Dot a,Dot b,Dot c,Dot d){return min(min(dtl(a,b,c),dtl(a,b,d)),min(dtl(c,d,a),dtl(c,d,b)));}
float work(Dot * a,Dot * b,int n,int m)
{
	Dot t;
	float ans=1e9;
	int i,ymin=0,ymax=0;
	for(i=0;i<n;i++)
		if(a[i].y<a[ymin].y)
			ymin=i;
	for(i=0;i<m;i++)
		if(b[i].y>b[ymax].y)
		   ymax=i;
	a[n]=a[0];b[m]=b[0];
	for(i=0;i<n;i++)
	{
		t=a[ymin+1]-a[ymin];
		while(t*(b[ymax]-a[ymin])<t*(b[ymax+1]-a[ymin]))//找到当前向量面积不小于下一个向量面积即可
			ymax=(ymax+1)%m;
		ans=min(ans,ltl(a[ymin],a[ymin+1],b[ymax],b[ymax+1]));
		ymin=(ymin+1)%n;
	}
	return ans;
}
int main()
{
	int i,n,m;
	Dot a[10010],b[10010];
	while(scanf("%d%d",&n,&m)&&n!=0||m!=0)
	{
		for(i=0;i<n;i++)
			scanf("%f%f",&a[i].x,&a[i].y);//单精度跑得快,而且精度是1e-6,对于此题,够用了
		for(i=0;i<m;i++)
			scanf("%f%f",&b[i].x,&b[i].y);
		printf("%.3f\n",work(a,b,n,m));//精度在1e-3就够了
	}
}
时间: 2024-11-07 10:52:39

旋转卡壳解poj3608Bridge Across Islands的相关文章

【旋转卡壳】poj3608 Bridge Across Islands

给你俩凸包,问你它们的最短距离. 咋做就不讲了,经典题,网上一片题解. 把凸包上的点逆时针排序.可以取它们的平均点,然后作极角排序. 旋转卡壳其实是个很模板化的东西-- 先初始化分别在凸包P和Q上取哪个点,一般在P上取纵坐标最小的点,在Q上取纵坐标最大的点 for i=1 to n(n是凸包P上的点数) { while(两条边的叉积>0) { 凸包Q上的点++ } 计算当前两条边之间的答案(或者说每条边的2个端点到另一条边的答案) 凸包P上的点++ } #include<cstdio>

Bridge Across Islands POJ - 3608 旋转卡壳求凸包最近距离

\(\color{#0066ff}{题目描述}\) 几千年前,有一个小王国位于太平洋的中部.王国的领土由两个分离的岛屿组成.由于洋流的冲击,两个岛屿的形状都变成了凸多边形.王国的国王想建立一座桥来连接这两个岛屿.为了把成本降到最低,国王要求你,主教,找到两个岛屿边界之间最小的距离. \(\color{#0066ff}{输入格式}\) 输入由几个测试用例组成. 每个测试用两个整数n,m(3≤n,m≤10000)开始 接下来的n行中的每一行都包含一对坐标,用来描述顶点在一个凸多边形中的位置. 下一条

POJ 3608 两凸包最近距离 旋转卡壳

Bridge Across Islands Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8071   Accepted: 2364   Special Judge Description Thousands of thousands years ago there was a small kingdom located in the middle of the Pacific Ocean. The territory

HDOJ 2202 最大三角形 凸包旋转卡壳求最大三角形面积

凸包旋转卡壳求最大三角形面积 最大三角形 Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3316    Accepted Submission(s): 1119 Problem Description 老师在计算几何这门课上给Eddy布置了一道题目,题目是这样的:给定二维的平面上n个不同的点,要求在这些点里寻找三个点,使他们构成的三角

旋转卡壳算法及应用 (参考论文)

多看论文开眼界! 转自:http://blog.csdn.net/acmaker/article/details/3188177 一.目录 一些历史: 1978年, M.I. Shamos's Ph.D. 的论文"Computational Geometry"标志着计算机科学的这一领域的诞生. 当时他发表成果的是一个寻找凸多边形直径的一个非常简单的算法, 即根据多边形的一对点距离的最大值来确定. 后来直径演化为由一对对踵点对来确定. Shamos提出了一个简单的 O(n) 时间的算法来

旋转卡壳总结

[+] 目录(?)[+] 以下所有文章均转载( http://blog.csdn.net/acmaker/article/details/3176910) 转载请注明出处! 1.旋转卡壳——翻译说明文档 前一段时间看了一位国外大牛的网站,是关于旋转卡壳技术的,内容很不错,就尝试着翻译一下. 关于旋转卡壳技术,最早是在刘汝佳.黄亮的<算法艺术与信息学竞赛>上看到的,是计算几何相关的技术,开始觉得很神奇,因为其对于凸多边形的问题给出了很好的解决方案,于是上网查了一下,就发现了这份资料. 通过个人的

旋转卡壳部分模板

凸包直径 旋转卡壳凸包直径详解 //计算凸包直径,输入凸包ch,顶点个数为n,按逆时针排列,输出直径的平方 int rotating_calipers(int n) { int q = 1; int ans = 0; ch[n] = ch[0]; for(int i = 0 ; i < n; i++) { while(mul(ch[i+1],ch[q+1],ch[i])>mul(ch[i+1],ch[q],ch[i]))//枚举凸包一条边并扫描其它点,通过计算三角形面积的方法找到最远的点 q

poj 3608(旋转卡壳求解两凸包之间的最短距离)

Bridge Across Islands Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9768   Accepted: 2866   Special Judge Description Thousands of thousands years ago there was a small kingdom located in the middle of the Pacific Ocean. The territory

[luogu1452]Beauty Contest【凸包+旋转卡壳】

题目大意 求出平面最远点对距离的平方. 分析 此题我wa了好久,第一是凸包写错了,后面又是旋转卡壳写错了..自闭3s. 题解应该是旋转卡壳,但是有人用随机化乱搞过掉了Orz. 讲讲正解. 我们先求出所有点的凸包,然后每一次更新对踵点,就像一个尺子一样卡着这个凸包的每一条边,然后计算两个点对之间的距离就可以了. 代码(借鉴了一下别人的代码) #include <bits/stdc++.h> #define ll long long #define ms(a, b) memset(a, b, si