题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6697

题意:现在在平面上有nnn条线段,并且定义线段xxx和线段yyy的最短距离为在xxx上任取一点和yyy上任取一点,最小的两点之间距离为两线段的最短距离。

解题心得:

  • 先分析复杂度,nnn的范围是100001000010000,如果直接n2n^2n2暴力加上TTT组数据肯定会超时。这个时候可以按线段的左端点的xxx排序,这样在按顺序枚举任意两条直线的时候如果右侧线段左端点xxx值左侧线段右端点xxx值的差值大于目前找到的答案,这个时候可以跳出第二重循环。就是暴力的时候剪枝。
  • 然后就是两个线段怎么求最小距离,设现在一个三维空间内有四个点,分别是ABCDABCDABCD,坐标分别是A(x1,y1,z1)A(x1, y1, z1)A(x1,y1,z1),B(x2,y2,z2)B(x2, y2, z2)B(x2,y2,z2),C(x3,y3,z3)C(x3, y3, z3)C(x3,y3,z3),D(x4,y4,z4)D(x4, y4, z4)D(x4,y4,z4),两条线段分别是ABABAB和CDCDCD。设P,QP,QP,Q分别为在ABABAB和CDCDCD上的点,P,QP,QP,Q可以用参数方程表示,PPP可以表示为:{X=x1+S(x2−x1)Y=y1+S(y2−y1)Z=z1+S(z2−z1)\left\{\begin{matrix} & X=x1+S(x2-x1) & \\ & Y=y1+S(y2-y1) & \\ & Z=z1+S(z2-z1) & \end{matrix}\right.⎩⎨⎧​​X=x1+S(x2−x1)Y=y1+S(y2−y1)Z=z1+S(z2−z1)​​QQQ可以表示为:{U=x3+T(x4−x3)V=y3+T(y4−y3)W=z3+T(z4−z3)\left\{\begin{matrix} & U=x3+T(x4-x3) & \\ & V=y3+T(y4-y3) & \\ & W=z3+T(z4-z3) & \end{matrix}\right.⎩⎨⎧​​U=x3+T(x4−x3)V=y3+T(y4−y3)W=z3+T(z4−z3)​​
    参数T和S必须满足0&lt;T&lt;10&lt;T&lt;10<T<1且0&lt;S&lt;10&lt;S&lt;10<S<1这个时候P,QP,QP,Q两点才在线段上,否则是在线段的延长线上。两点间的距离PQ=(X−U)2+(Y−V)2+(Z−W)2PQ=\sqrt{(X-U)^2+(Y-V)^2+(Z-W)^2}PQ=(X−U)2+(Y−V)2+(Z−W)2​,设距离的平方为f(s,t)=[(x1−x3)+S(x2−x1)−T(x4−x3)]2+[(y1−y3)+S(y2−y1)−T(y4−y3)]2+[(z1−z3)+S(x2−x1)+T(z4−z3)]2f(s,t)=[(x1-x3)+S(x2-x1)-T(x4-x3)]^2+[(y1-y3)+S(y2-y1)-T(y4-y3)]^2+[(z1-z3)+S(x2-x1)+T(z4-z3)]^2f(s,t)=[(x1−x3)+S(x2−x1)−T(x4−x3)]2+[(y1−y3)+S(y2−y1)−T(y4−y3)]2+[(z1−z3)+S(x2−x1)+T(z4−z3)]2
    这个时候我们需要得到的是f(s,t)f(s,t)f(s,t)的最小值,所以对f(s,t)f(s,t)f(s,t)分别求对sss和ttt的偏导数,并且令偏导数为000,联立可以可以得到{[(x2−x1)2+(y2−y1)2+(z2−z1)2]S−[(x2−x1)(x4−x3)+(y2−y1)(y4−y3)+(z2−z1)(z4−z3)]T=(x1−x2)(x1−x3)+(y1−y2)(y1−y3)+(z1−z2)(z1−z3)−[(x2−x1)(x4−x3)+(y2−y1)(y4−y3)+(z2−z1)(z4−z3)]S+[(x4−x3)2+(y4−y3)2+(z4−z3)2]T=(x1−x3)(x4−x3)+(y1−y3)(y4−y3)+(z1−z3)(z4−z3)\left\{\begin{matrix} &amp; [(x2-x1)^2+(y2-y1)^2+(z2-z1)^2]S-[(x2-x1)(x4-x3)+(y2-y1)(y4-y3)+(z2-z1)(z4-z3)]T=(x1-x2)(x1-x3)+(y1-y2)(y1-y3)+(z1-z2)(z1-z3) &amp; \\ &amp; -[(x2-x1)(x4-x3)+(y2-y1)(y4-y3)+(z2-z1)(z4-z3)]S+[(x4-x3)^2+(y4-y3)^2+(z4-z3)^2]T=(x1-x3)(x4-x3)+(y1-y3)(y4-y3)+(z1-z3)(z4-z3) &amp; \end{matrix}\right.{​[(x2−x1)2+(y2−y1)2+(z2−z1)2]S−[(x2−x1)(x4−x3)+(y2−y1)(y4−y3)+(z2−z1)(z4−z3)]T=(x1−x2)(x1−x3)+(y1−y2)(y1−y3)+(z1−z2)(z1−z3)−[(x2−x1)(x4−x3)+(y2−y1)(y4−y3)+(z2−z1)(z4−z3)]S+[(x4−x3)2+(y4−y3)2+(z4−z3)2]T=(x1−x3)(x4−x3)+(y1−y3)(y4−y3)+(z1−z3)(z4−z3)​​
    对于上式进行求解可以得到SSS和TTT的值,这个时候若SSS和TTT都满足(0,1)(0, 1)(0,1)区间则可以直接得到P,QP,QP,Q两点具体的值,这样就得到了PQPQPQ的距离。
    若S,TS,TS,T的范围不满足条件,则可以先得到A,BA,BA,B两点到线段CDCDCD的距离dis1,dis2dis1,dis2dis1,dis2,C,DC,DC,D两点到线段ABABAB的距离dis3dis3dis3,dis4dis4dis4,这时两线段的距离就是min(dis1,dis2,dis3,dis4)min(dis1, dis2, dis3, dis4)min(dis1,dis2,dis3,dis4)。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e5+100;struct Seg {double x1, x2, y1, y2;bool operator < (const Seg&x) const {return x1 < x.x1;}
}seg[maxn];int t, n;
double ans;void init() {ans = 2e18;scanf("%d",&n);for(int i=1;i<=n;i++) {scanf("%lf%lf%lf%lf", &seg[i].x1, &seg[i].y1, &seg[i].x2, &seg[i].y2);if(seg[i].x2 < seg[i].x1) {swap(seg[i].x1, seg[i].x2);swap(seg[i].y1, seg[i].y2);}}sort(seg+1, seg+1+n);
}bool checke(int x, int y) {double dis1 = seg[x].x2;double dis2 = seg[y].x1;if(dis2 - dis1 > ans) return true;return false;
}double PointToSegDist(double x, double y, double x1, double y1, double x2, double y2)//点到直线距离
{double cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);if (cross <= 0) return sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));double d2 = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);if (cross >= d2) return sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));double r = cross / d2;double px = x1 + (x2 - x1) * r;double py = y1 + (y2 - y1) * r;return sqrt((x - px) * (x - px) + (py - y) * (py - y));
}double get_dis(int x, int y) {double k1, k2, k3, k4, a1, a2;double x1 = seg[x].x1, x2 = seg[x].x2, y1 = seg[x].y1, y2 = seg[x].y2;double x3 = seg[y].x1, x4 = seg[y].x2, y3 = seg[y].y1, y4 = seg[y].y2;double z2 = 0, z1 = 0, z4 = 0, z3 = 0;//二维平面则z坐标没有使用k1 = ((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));k2 = -((x2-x1)*(x4-x3) + (y2-y1)*(y4-y3) + (z2-z1)*(z4-z3));a1 = (x1-x2)*(x1-x3) + (y1-y2)*(y1-y3) + (z1-z2)*(z1-z3);k3 = -((x2-x1)*(x4-x3) + (y2-y1)*(y4-y3) + (z2-z1)*(z4-z3));k4 = (x4-x3)*(x4-x3) + (y4-y3)*(y4-y3) + (z4-z3)*(z4-z3);a2 = (x1-x3)*(x4-x3) + (y1-y3)*(y4-y3) + (z1-z3)*(z4-z3);double temp_k = k1;k1 *= k3;k2 *= k3;a1 *= k3;k3 *= temp_k;k4 *= temp_k;a2 *= temp_k;double T = (a1-a2)/(k2-k4);double S = (a1-k2*T)/k1;if(S >=0 && S <= 1.0 && T >= 0 && T <= 1.0) {double X = x1 + (x2-x1)*S;double Y = y1 + (y2-y1)*S;double Z = z1 + (z2-z1)*S;double X1 = x3 + (x4-x3)*T;double Y1 = y3 + (y4-y3)*T;double Z1 = z3 + (z4-z3)*T;return sqrt((X-X1)*(X-X1) + (Y-Y1)*(Y-Y1) + (Z-Z1)*(Z-Z1));} else {double dis1 = PointToSegDist(x1, y1, x3, y3, x4, y4);double dis2 = PointToSegDist(x2, y2, x3, y3, x4, y4);double dis3 = PointToSegDist(x3, y3, x1, y1, x2, y2);double dis4 = PointToSegDist(x4, y4, x1, y1, x2, y2);return min(min(dis1, dis2), min(dis3, dis4));}
}void solve() {for(int i=1;i<=n;i++) {for(int j=i+1;j<=n;j++) {if(checke(i, j)) break;else ans = min(ans, get_dis(i, j));}}
}int main() {//    freopen("1.in.txt", "r", stdin);scanf("%d", &t);while(t--) {init();solve();printf("%.9f\n", ans);}
}

HDU:6697-Closest Pair of Segments(空间内的最近线段)相关推荐

  1. 数据结构与算法笔记:分治策略之Greatest Slice,2-Way Merge,Counting Inversions,linearSelect,Diameter,Closest Pair

    Divide and Conquer 分而治之概述 分而治之,就像是团队合作,将一项工作分解成不同的成员去处理 一般情况,我们面临的规模比较大,用n来表示,我们会把它分为若干个任务来同步进行处理 一般 ...

  2. 将类别加入到别人的名称空间内

    怎样把自己的类别加入到别人的名称空间内,在引用时,能在别人的名称空间下使用到自己写的类别. 这是一位台湾朋友问及此问题,因此录制一个视频做演示: 视频文件格式:.wmv:大小:9,706KB:长度:0 ...

  3. 树形DP+树状数组 HDU 5877 Weak Pair

    1 //树形DP+树状数组 HDU 5877 Weak Pair 2 // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 3 // 这道题要 ...

  4. 【CodeForces - 312C】The Closest Pair (思维)

    题干: Currently Tiny is learning Computational Geometry. When trying to solve a problem called "T ...

  5. 关于ArcGIS动态图层空间内栅格数据,JS前端显示颜色不正确的解决方案

    关于ArcGIS动态图层空间内栅格数据,JS前端显示颜色不正确的解决方案 参考文章: (1)关于ArcGIS动态图层空间内栅格数据,JS前端显示颜色不正确的解决方案 (2)https://www.cn ...

  6. 还在为QQ空间的大量广告而苦恼吗? 教你如何彻底的清除QQ空间内广告!!!

    还在为QQ空间的大量广告而苦恼吗? 教你如何彻底的清除QQ空间内广告!!! 大家好,我叫亓官劼(qí guān jié ),在CSDN中记录学习的点滴历程,时光荏苒,未来可期,加油~博客地址为:亓官劼 ...

  7. 一文读懂BEV空间内的特征级融合

    交流群 | 进"传感器群/滑板底盘群"请加微信号:xsh041388 交流群 | 进"域控制器群/操作系统群"请加微信号:ckc1087 备注信息:传感器/滑板 ...

  8. MaxCompute 项目空间内的访问控制和权限管理

    项目空间内的访问控制分为以下五类: 用户管理 ACL授权 Policy授权 角色管理 基于标签的访问控制管理 用户管理 任意非项目空间Owner用户必须被加入MaxCompute项目空间中,并被授予相 ...

  9. 空间(3D)转换:使用transform属性实现元素在空间内的位移、旋转、缩放等效果

    空间转换 目标:使用transform属性实现元素在空间内的位移.旋转.缩放等效果 空间:是从坐标轴角度定义的. x .y 和z三条坐标轴构成了一个立体空间,z轴位置与视线方向相同. 空间转换也叫3D ...

最新文章

  1. 2021年大数据Spark(二十九):SparkSQL案例四开窗函数
  2. cifar-10 cnn 分类
  3. IP地址与MAC地址的区别
  4. c# 测试运行时间毫秒级
  5. CS144 lab2 笔记
  6. java三大特性——封装,继承,多态
  7. WX微信小程序路由API使用
  8. 如何用纯 CSS 创作一双黑暗中的眼睛
  9. (70)Verilog HDL测试激励:复位激励2
  10. 大数据_Flink_流式处理_简介_流数据处理的应用行业---Flink工作笔记0003
  11. Electron —— Cannot find module ‘index.js’
  12. python爬取快手视频_【原创开源】快手爬虫,根据id批量爬取用户的所有图集和视频...
  13. 电脑自动同步服务器时间bat,关于电脑时间自动同步校准方法
  14. 结果导向和自管理的联系
  15. 【绘图】3D点图 及绘图关系matplotlib中plt系列
  16. GetDC() ReleaseDC()引起的内存泄漏
  17. “创药网”-创新药领域专业资讯网站​
  18. CAD图纸打印文字显示空心怎么办?
  19. libtool 的使用。
  20. 优矩互动通过聆讯,靠抖音、京东养活的流量生意“二道贩子”?

热门文章

  1. 【OR】YALMIP uncertain
  2. 机器学习实战之k-近邻算法识别手写数字(含拍照检验步骤详解)
  3. Blender全流程制作!全网百万点赞的中传动画专业学生毕设作品《象群挽歌》主创专访...
  4. 购买李宁老师视频课程,赶快来领优惠劵啊,数量有限,先到先得。
  5. js拼接URL字符串
  6. 免费ocr 吊打百度收费ocr 摄像头直接图片识别文字,本地搭建ocr服务器
  7. redis集群读写,容错切换,从属调整,扩容,缩容
  8. linux获取文件引用计数,linux-.6内核模块引用计数的实现(try_module_get和module_put).doc...
  9. 新生报到系统_你的宿舍你做主!成电研究生新生选房系统上线
  10. 软件测试7年的工程师,讲述当初是怎么突破的瓶颈?少走弯路