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> ...
随机推荐
- Notepad++在编程使用时的小技巧
http://blog.csdn.net/freewaywalker/article/details/8010790 为了编程时更快捷和适应个人习惯,我们可以对Notepad++进行一系列的设置,这当 ...
- Initializer block.
Ref: Initializing Fields Instance initializers are permitted to refer to the current object via the ...
- offie2010设置前两页和后面显示不同页码的方法
1.在需要设置的第二页文档后面点击一下,让光标进入,再菜单上找到"页面布局"—“分栏符”—“下一页”(如图) 2.插入—页码—页面底端(如图) 3.点击页码附近的—“链接到前一页面 ...
- phpcms v9后台美化需要修改的部分整理
PHPcms后台登陆后的页面修改 Phpcms->modules->admin->templates->main.tpl.php 1,安全提示部分 <h6>< ...
- lmsw - 加载机器状态字
将源操作数加载到机器状态字,即寄存器 CR0 的位 0 到 15.源操作数可以是 16 位通用寄存器或内存位置.只有源操作数的低 4 位(也就是 PE.MP.EM 及 TS 标志)会加载到 CR0.C ...
- ThinkPHP框架下,jq实现在div中添加标签并且div的大小会随之变化
php初学者,有什么不对的还请指正. 首先是在html页面中用jq实现添加标签:divAchivePersonnal是select所在的div的外层div,divselectAchivePersonn ...
- php 获取域名的whois 信息
首先先了解几个文件操作函数: fwrite() 函数写入文件(可安全用于二进制文件). fwrite() 把 string 的内容写入文件指针 file 处. 如果指定了 length,当写入了 le ...
- JSP语法
第3章 JSP语法 [本章专家知识导学] JSP是建立在Java语言基础上的一种Web程序设计语言,具有自己特有的用法和指令.本章首先介绍JSP页面的程序结构,然后讲述JSP程序中经常用到基本的面向 ...
- JS拖动div的原理
要实现移动窗体,首先要捕获三个参数:1.a = 鼠标点击时的坐标.2.b = 被移动窗体的左顶点坐标.3.c = 鼠标移动时的坐标.然后还要算出你鼠标无论点击窗体哪个位置,移动改变的都是 (d = 窗 ...
- MySQL ubuntu启动
service mysql start 启动 service mysql restart 重启 service mysql stop 停止 mysql -uroot -ppassword 登入mysq ...