poj 3608 旋转卡壳求不相交凸包最近距离;
题目链接:http://poj.org/problem?id=3608
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = ;
const int maxe = ;
const int INF = 0x3f3f3f;
const double eps = 1e-;
const double PI = acos(-1.0); struct Point{
double x,y;
Point(double x=, double y=) : x(x),y(y){ } //构造函数
};
typedef Point Vector; 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 p){return Vector(A.x*p,A.y*p);}
Vector operator / (Vector A , double p){return Vector(A.x/p,A.y/p);} bool operator < (const Point& a,const Point& b){
return a.x < b.x ||( a.x == b.x && a.y < b.y);
} int dcmp(double x){
if(fabs(x) < eps) return ;
else return x < ? - : ;
}
bool operator == (const Point& a, const Point& b){
return dcmp(a.x - b.x) == && dcmp(a.y - b.y) == ;
} ///向量(x,y)的极角用atan2(y,x);
double Dot(Vector A, Vector B){ return A.x*B.x + A.y*B.y; }
double Length(Vector A) { return sqrt(Dot(A,A)); }
double Angle(Vector A, Vector B) { return acos(Dot(A,B) / Length(A) / Length(B)); }
double Cross(Vector A, Vector B) { return A.x*B.y - A.y * B.x; } Vector Rotate(Vector A, double rad) { return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad)); } ///求点P到线段AB的距离,先看Q点在线段外还是内;利用点积就可以,
double DistanceToSegment(Point P,Point A,Point B){
if(A == B) return Length(P-A);
Vector v1 = B - A,v2 = P - A,v3 = P - B;
if(dcmp(Dot(v1,v2)) < ) return Length(v2);
else if(dcmp(Dot(v1,v3) > )) return Length(v3);
else return fabs(Cross(v1,v2))/Length(v1);
}
///求线段AB与线段CD的距离;
double DistanceBetweenSegment(Point A,Point B,Point C,Point D){
return min(min(DistanceToSegment(A,C,D),DistanceToSegment(B,C,D)),min(DistanceToSegment(C,A,B),DistanceToSegment(D,A,B)));
} //凸包:
/**Andrew算法思路:首先按照先x后y从小到大排序(这个地方没有采用极角逆序排序,所以要进行两次扫描),删除重复的点后得到的序列p1,p2.....,然后把p1和p2放到凸包中。从p3开始,当新的
点在凸包“前进”方向的左边时继续,否则依次删除最近加入凸包的点,直到新点在左边;**/ //Goal[]数组模拟栈的使用;
int ConvexHull(Point* P,int n,Point* Goal){
sort(P,P+n);
int m = unique(P,P+n) - P; //对点进行去重;
int cnt = ;
for(int i=;i<m;i++){ //求下凸包;
while(cnt> && dcmp(Cross(Goal[cnt-]-Goal[cnt-],P[i]-Goal[cnt-])) <= ) cnt--;
Goal[cnt++] = P[i];
}
int temp = cnt;
for(int i=m-;i>=;i--){ //逆序求上凸包;
while(cnt>temp && dcmp(Cross(Goal[cnt-]-Goal[cnt-],P[i]-Goal[cnt-])) <= ) cnt--;
Goal[cnt++] = P[i];
}
if(cnt > ) cnt--; //减一为了去掉首尾重复的;
return cnt;
} double solve(Point* P1,Point* Q1,int Minid,int Maxid,int N,int M){
double temp,ret = 1e5;
P1[N] = P1[]; Q1[M] = Q1[];
for(int i=;i<N;i++){
while(temp = dcmp(Cross(Q1[Maxid]-Q1[Maxid+],P1[Minid+]-P1[Minid]))> ) //这一步最难理解:要理解怎样才能使Q1[Maxid]Q1[Maxid+1]这条线段最接近线段P1[Minid+1]P1[Minid];
Maxid = (Maxid+)%M; // 先以P1[Minid]为定点,旋转Q1[Maxid];
if(temp < ) ret = min(ret,DistanceToSegment(Q1[Maxid],P1[Minid],P1[Minid+]));
else ret = min(ret,DistanceBetweenSegment(P1[Minid],P1[Minid+],Q1[Maxid],Q1[Maxid+]));\
Minid = (Minid + )%N; //再旋转P1[Minid];
}
return ret;
}
Point read_point(){
Point A;
scanf("%lf %lf",&A.x,&A.y);
return A;
} /*******************************分割线******************************/
Point P[maxn],Q[maxn];
Point P1[maxn],Q1[maxn]; //利用凸包算法使坐标逆时针化后的存储;
int N,M;
int Maxid,Minid; void GetMaxandMin(int& Maxid,int& Minid){
Maxid = ; Minid = ;
for(int i=;i<N;i++){
if(P1[i].y < P1[Minid].y) Minid = i;
}
for(int i=;i<M;i++){
if(Q1[i].y > Q1[Maxid].y) Maxid = i;
}
} int main()
{
//freopen("E:\\acm\\input.txt","r",stdin); while(cin>>N>>M && N+M){
for(int i=;i<N;i++) P[i] = read_point();
N = ConvexHull(P,N,P1); for(int i=;i<M;i++) Q[i] = read_point();
M = ConvexHull(Q,M,Q1); GetMaxandMin(Maxid,Minid); double ans = solve(P1,Q1,Minid,Maxid,N,M);
printf("%.5f\n",ans);
}
}
poj 3608 旋转卡壳求不相交凸包最近距离;的更多相关文章
- Bridge Across Islands POJ - 3608 旋转卡壳求凸包最近距离
\(\color{#0066ff}{题目描述}\) 几千年前,有一个小王国位于太平洋的中部.王国的领土由两个分离的岛屿组成.由于洋流的冲击,两个岛屿的形状都变成了凸多边形.王国的国王想建立一座桥来连接 ...
- poj 3608(旋转卡壳求解两凸包之间的最短距离)
Bridge Across Islands Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9768 Accepted: ...
- 「POJ-3608」Bridge Across Islands (旋转卡壳--求两凸包距离)
题目链接 POJ-3608 Bridge Across Islands 题意 依次按逆时针方向给出凸包,在两个凸包小岛之间造桥,求最小距离. 题解 旋转卡壳的应用之一:求两凸包的最近距离. 找到凸包 ...
- POJ 3608 旋转卡壳
思路: 旋转卡壳应用 注意点&边 边&边 点&点 三种情况 //By SiriusRen #include <cmath> #include <cstdi ...
- POJ3608(旋转卡壳--求两凸包的最近点对距离)
题目:Bridge Across Islands 分析:以下内容来自:http://blog.csdn.net/acmaker/article/details/3178696 考虑如下的算法, 算法的 ...
- POJ2187 旋转卡壳 求最长直径
给定平面上的一些散点集,求最远两点距离的平方值. 题解: 旋转卡壳求出凸包,然后根据单调性,求出最远两点的最大距离 #pragma GCC optimize(2) #pragma G++ optimi ...
- POJ 2187 Beauty Contest【旋转卡壳求凸包直径】
链接: http://poj.org/problem?id=2187 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22013#probl ...
- poj 2187 Beauty Contest , 旋转卡壳求凸包的直径的平方
旋转卡壳求凸包的直径的平方 板子题 #include<cstdio> #include<vector> #include<cmath> #include<al ...
- UVa 1453 - Squares 旋转卡壳求凸包直径
旋转卡壳求凸包直径. 参考:http://www.cppblog.com/staryjy/archive/2010/09/25/101412.html #include <cstdio> ...
随机推荐
- 关于百度 UEditor的使用
1.文件路径的配置: 注意:在页面上需要指定editor文件所在的路径,否则报错 后面有时间,再说说 kindEditor和 bootstrap3的summernote的 Editor, fck ...
- jQuery AJAX实现调用页面后台方法
1.新建demo.aspx页面.2.首先在该页面的后台文件demos.aspx.cs中添加引用. using System.Web.Services; 3.无参数的方法调用. 大家注意了,这个版本不能 ...
- jquery选择器的使用方式
1.基本选择器 选择器 描述 返回 示例 代码说明 1 id选择器 根据指定的id匹配元素 单个元素 $("#one").css("background", ...
- CSS居中的方法总结
[水平居中] 行内:text-align:center; 定宽块状:1.left:0 right:0然后用margin: auto外边距填充,水平方向不会发生外边距叠加; 2.绝对定位(父元素定位不 ...
- (一)Nodejs - 框架类库 - Nodejs异步流程控制Async
简介 Async是一个流程控制工具包,提供了直接而强大的异步功能 应用场景 业务流程逻辑复杂,适应异步编程,减少回调的嵌套 安装 npm insatll async 函数介绍 Collections ...
- SGU 145.Strange People(无环K短路)
时间:0.25s空间:4m 题意: 其实就是求无环第K短路. 输入: 给出n,m,k,分别代表,n个点,m条边,第k长路. 接下来m行,三个整数x,y,z,分别代表x,y之间有条费用为x的双向路.保证 ...
- Bootstrap_表单_图标
在Bootstrap框架中是通过给元素添加“glyphicon”类名来实现,然后通过伪元素“:before”的“content”属性调取对应的icon编码: <span class=" ...
- devicePixelRatio
devicePixelRatio window.devicePixelRatio是设备上物理像素和逻辑像素的比例.公式表示就是:window.devicePixelRatio = 物理像素 / 逻辑像 ...
- dede取得指定栏目的链接
获取标签 typeid 为目录的 id {dede:type typeid='1'} <a href="[field:typelink /]">[field ...
- 解决xp共享的批处理文件
在空白地方点右键选择新建一个文本文档,将默认的“新建 文本文档.txt”文件名改名为以下红色加粗字体内容,再复制红色内容以下的黑字部分到改名后的文档.其他文件生成的方法相同.完成后根据需要双击CMD扩 ...