POJ 3608 凸包间最短距离(旋转卡壳)
| Time Limit: 1000MS | Memory Limit: 65536K | |||
| Total Submissions: 11539 | Accepted: 3395 | Special Judge | ||
Description
Thousands of thousands years ago there was a small kingdom located in the middle of the Pacific Ocean. The territory of the kingdom consists two separated islands. Due to the impact of the ocean current, the shapes of both the islands became convex polygons. The king of the kingdom wanted to establish a bridge to connect the two islands. To minimize the cost, the king asked you, the bishop, to find the minimal distance between the boundaries of the two islands.

Input
The input consists of several test cases.
Each test case begins with two integers N, M. (3 ≤ N, M ≤ 10000)
Each of the next N lines contains a pair of coordinates, which describes the position of a vertex in one convex polygon.
Each of the next M lines contains a pair of coordinates, which describes the position of a vertex in the other convex polygon.
A line with N = M = 0 indicates the end of input.
The coordinates are within the range [-10000, 10000].
Output
For each test case output the minimal distance. An error within 0.001 is acceptable.
Sample Input
4 4
0.00000 0.00000
0.00000 1.00000
1.00000 1.00000
1.00000 0.00000
2.00000 0.00000
2.00000 1.00000
3.00000 1.00000
3.00000 0.00000
0 0
Sample Output
1.00000
Source

思路:找到凸包 p 的 y 值最小点 yminP 和 q 的 y 值最大点ymaxQ,然后分别做切如图。那么AC×AD>AC×AB则说明B还不是离AC最近的点,所以++ymaxQ。
否则用 AC和 BD 两个线段的距离更新最近距离,并且++yminP,即考察P的下一条边。
具体实现时,同时旋转体现为逐步选取逆时针方向上的下一个顶点作为C或D、A或B,其实选择卡壳就是只要找到"当前向量面积不小于下一个向量面积"即可,再求两条线段间的最短距离。
代码:
//#include "bits/stdc++.h"
#include "cstdio"
#include "map"
#include "set"
#include "cmath"
#include "queue"
#include "vector"
#include "string"
#include "cstring"
#include "time.h"
#include "iostream"
#include "stdlib.h"
#include "algorithm"
#define db double
#define ll long long
#define vec vector<ll>
#define mt vector<vec>
#define ci(x) scanf("%d",&x)
#define cd(x) scanf("%lf",&x)
#define cl(x) scanf("%lld",&x)
#define pi(x) printf("%d\n",x)
#define pd(x) printf("%f\n",x)
#define pl(x) printf("%lld\n",x)
//#define rep(i, x, y) for(int i=x;i<=y;i++)
#define rep(i,n) for(int i=0;i<n;i++)
const int n = 1e4 + ;
const int mod = 1e9 + ;
const int mOD = mod - ;
const db eps = 1e-;
const db PI = acos(-1.0);
const int inf=0x3f3f3f3f;
using namespace std;
struct P
{
db x, y;
P() {}
P(db x, db y) : x(x), y(y) {}
P operator + (const P& p){ return P(x + p.x, y + p.y); }
P operator - (const P& p){ return P(x - p.x, y - p.y); }
P operator * (const db& d){ return P(x * d, y * d); }
bool operator < (const P& a) const
{
if (x != a.x) return x < a.x;
else return y < a.y;
}
db dot(const P& p) { return x * p.x + y * p.y; }
db det(const P& p) { return x * p.y - y * p.x; }
};
P p[n], q[n];
// 向量AB 与 AC 的叉积 如果叉积大于0,那么C在向量AB的逆时针方向,叉积小于0则在AB的顺时针方向。如果叉积等于0,则ABC共线。
db cross(P A, P B, P C) {return (B - A).det(C - A); }
// 向量AB 与 AC 的点积 如果点积的结果为0,那么这两个向量互相垂直
db mul(P A, P B, P C) {return (B - A).dot(C - A); }
// 两点距离
db dis(P A, P B){return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y)); } // 逆时针排序
void csort(P* p, int n)
{
for (int i = ; i < n - ; ++i)
{
db tmp = cross(p[i], p[i + ], p[i + ]);
if (tmp > eps) return;
else if (tmp < -eps)
{
reverse(p, p + n);
return;
}
}
} //计算C点到线段AB的最短距离
db ptl(P A, P B, P C)
{
if (dis(A, B) < eps) return dis(B, C);
if (mul(A, B, C) < -eps) return dis(A, C);
if (mul(B, A, C) < -eps) return dis(B, C);
return fabs(cross(A, B, C) / dis(A, B));
}
//求一条线段的两端点到另外一条线段的距离,反过来一样,共4种情况
db ltl(P A, P B, P C, P D)
{
return min(min(ptl(A, B, C), ptl(A, B, D)), min(ptl(C, D, A), ptl(C, D, B)));
}
db solve(P* p, P* q, int n, int m)
{
int pmi = , qmx = ;
for (int i = ; i < n; ++i) if (p[i].y < p[pmi].y) pmi = i; // P上y坐标最小的顶点
for (int i = ; i < m; ++i) if (q[i].y > q[qmx].y) qmx = i; // Q上y坐标最大的顶点
p[n] = p[]; // 为了方便,避免求余
q[m] = q[];
db tmp, ans = inf;
for (int i = ; i < n; ++i)
{
while (tmp = cross(p[pmi],p[pmi + ], q[qmx + ]) - cross(p[pmi],p[pmi + ], q[qmx]) > eps) qmx = (qmx + ) % m;
ans = min(ans, ltl(p[pmi], p[pmi + ], q[qmx], q[qmx + ]));
pmi = (pmi + ) % n;
}
return ans;
}
int main()
{
int n, m;
while (~scanf("%d%d", &n, &m) && n + m)
{
for (int i = ; i < n; ++i) cd(p[i].x),cd(p[i].y);
for (int i = ; i < m; ++i) cd(q[i].x),cd(q[i].y);
csort(p, n);
csort(q, m);
printf("%.5lf\n", solve(p, q, n, m));
}
return ;
}
POJ 3608 凸包间最短距离(旋转卡壳)的更多相关文章
- poj 3608 凸包间的最小距离
Bridge Across Islands Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7632 Accepted: ...
- POJ 3608 Bridge Across Islands [旋转卡壳]
Bridge Across Islands Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10455 Accepted: ...
- 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(凸包直径、旋转卡壳)
给定点集的最远两点的距离. 先用graham求凸包.旋(xuán)转(zhuàn)卡(qiǎ)壳(ké)求凸包直径. ps:旋转卡壳算法的典型运用 http://blog.csdn.net/hanch ...
- [Bzoj1069][Scoi2007]最大土地面积(凸包)(旋转卡壳)
1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 3629 Solved: 1432[Submit][Sta ...
- [模板] 计算几何2: 自适应Simpson/凸包/半平面交/旋转卡壳/闵可夫斯基和
一些基本的定义在这里: [模板] 计算几何1(基础): 点/向量/线/圆/多边形/其他运算 自适应Simpson Simpson's Rule: \[ \int ^b_a f(x)dx\approx ...
- POJ - 2079:Triangle (旋转卡壳,求最大三角形)
Given n distinct points on a plane, your task is to find the triangle that have the maximum area, wh ...
- POJ - 3608 Bridge Across Islands【旋转卡壳】及一些有趣现象
给两个凸包,求这两个凸包间最短距离 旋转卡壳的基础题 因为是初学旋转卡壳,所以找了别人的代码进行观摩..然而发现很有意思的现象 比如说这个代码(只截取了关键部分) double solve(Point ...
- poj 2187 凸包加旋转卡壳算法
题目链接:http://poj.org/problem?id=2187 旋转卡壳算法:http://www.cppblog.com/staryjy/archive/2009/11/19/101412. ...
随机推荐
- intellijidea课程 intellijidea神器使用技巧 5-1 svn相关
subversion ==> show local history 查看历史记录 Ctrl D 历史记录对比 ctrl alt z 复原
- h5:erver-Sent Events
对于一般的 Web 应用开发,大多数开发人员并不陌生.在 Web 应用中,浏览器和服务器之间使用的是请求 / 响应的交互模式.浏览器发出请求,服务器根据收到的请求来生成相应的响应.浏览器再对收到的响应 ...
- ASP.NET MVC 音乐商店 - 5. 通过支架创建编辑表单
在上一章,我们已经从数据库获取数据,然后显示出来,这一章,我们将允许编辑数据. 创建 StoreManagerController 控制器 我们将要创建称为 StoreManager 的控制器,对于这 ...
- adb使用wifi无线连接调试Android设备
先上官方原文: Wireless usage adb is usually used over USB. However, it is also possible to use over Wi-Fi, ...
- (转)轻松解决 MyEclipse、Eclipse 编译时提示 @Override The method of type must override a superclass method 即 @Override 标注问题
刚才在把工程从其他地方导入到自己机子的 MyEclipse 下时,出现了 The method of type must override a superclass method ,提示的是实现类必须 ...
- Java1.7新特性
1.switch语句支持字符串变量 public String getTypeOfDayWithSwitchStatement(String dayOfWeekArg) { String typeOf ...
- 初识Python(三)
一.作用域 对于变量的作用域,执行声明并在内存中存在,该变量就可以在后续的代码中使用: 外层变量,可以被内层变量使用:内层变量,也可以被外层变量使用: 如下示例: #!/usr/bin/env pyt ...
- org.apache.xmlbeans.XmlException: error: does not close tag
使用myeclipse的jax自动生成webservice , 或者serviceImpl通过@webservice来实现webservice时, 使用soap UI (我测试使用的版本 5.2.1) ...
- "COM Surrogate 已停止工作"解决方案(windows7 64位及32位)
根据图示步骤,将以下文件添加至“数据执行保护”的例外列表中. 64位:C:Windows\SysWOW64\dllhost.exe 32位:C:\Windows\System32\dllhost.ex ...
- IOS 制作版本新特性
创建版本新特性 页面(存放图片) HMNewfeatureViewController.m #define HMNewfeatureImageCount 4 #import "HMNewfe ...