HDU 4741 Save Labman No.004
2015-11-12 12:57
274 查看
题意:有两条异面直线,在这两条直线上分别各找一点,使得这两点间的距离最短
P1P_1是直线L1上的点,S1S_1是直线L1L_1的方向向量
P2P_2是直线L2L_2上的点,S2S_2是直线L2L_2的方向向量
这样S1×S2S_1×S_2是L1L_1和L2L_2的公垂线
不妨设P1+t1S1P_1+t_1S_1和P2+t2S2P_2+t_2S_2是满足题意的一对点,则
P1+t1S1=P2+t2S2+t(S1×S2)P_1+t_1S_1= P_2+t_2S_2+t(S_1×S_2)
移项得
t1S1=(P2−P1)+t2S2+t(S1×S2)t_1S_1= (P_2-P_1)+t_2S_2+t(S_1×S_2)
为消t2t_2,左右都叉乘S2S_2得
t1(S1×S2)=(P2−P1)×S2+t((S1×S2)×S2)t_1(S_1×S_2)= (P_2-P_1)×S_2+t((S_1×S_2)×S_2)
为了把t1的系数变成数左右都点乘S1×S2得
t1|S1×S2|2=((P2−P1)×S2)⋅(S1×S2)t_1|S_1×S_2|^2=((P_2-P_1)×S_2)\cdot(S_1×S_2)
化简得
t1=((P2−P1)×S2)⋅(S1×S2)|S1×S2|2 t_1 = \dfrac{((P_2-P_1)×S_2)\cdot(S_1×S_2)}{|S_1×S_2|^2}
同理
t2=((P1−P2)×S1)⋅(S2×S1)|S2×S1|2 t_2 = \dfrac{((P_1-P_2)×S_1)\cdot(S_2×S_1)}{|S_2×S_1|^2}
这样点就求出来了
P1P_1是直线L1上的点,S1S_1是直线L1L_1的方向向量
P2P_2是直线L2L_2上的点,S2S_2是直线L2L_2的方向向量
这样S1×S2S_1×S_2是L1L_1和L2L_2的公垂线
不妨设P1+t1S1P_1+t_1S_1和P2+t2S2P_2+t_2S_2是满足题意的一对点,则
P1+t1S1=P2+t2S2+t(S1×S2)P_1+t_1S_1= P_2+t_2S_2+t(S_1×S_2)
移项得
t1S1=(P2−P1)+t2S2+t(S1×S2)t_1S_1= (P_2-P_1)+t_2S_2+t(S_1×S_2)
为消t2t_2,左右都叉乘S2S_2得
t1(S1×S2)=(P2−P1)×S2+t((S1×S2)×S2)t_1(S_1×S_2)= (P_2-P_1)×S_2+t((S_1×S_2)×S_2)
为了把t1的系数变成数左右都点乘S1×S2得
t1|S1×S2|2=((P2−P1)×S2)⋅(S1×S2)t_1|S_1×S_2|^2=((P_2-P_1)×S_2)\cdot(S_1×S_2)
化简得
t1=((P2−P1)×S2)⋅(S1×S2)|S1×S2|2 t_1 = \dfrac{((P_2-P_1)×S_2)\cdot(S_1×S_2)}{|S_1×S_2|^2}
同理
t2=((P1−P2)×S1)⋅(S2×S1)|S2×S1|2 t_2 = \dfrac{((P_1-P_2)×S_1)\cdot(S_2×S_1)}{|S_2×S_1|^2}
这样点就求出来了
#include <cstdio> #include <math.h> struct P { double x, y, z; P(){} P(double _x, double _y, double _z){x = _x; y = _y; z = _z;} }p1, p3, p2, p4, s1, s2; P operator + (P a, P b) {return P(a.x + b.x, a.y + b.y, a.z + b.z);} P operator - (P a, P b) {return P(a.x - b.x, a.y - b.y, a.z - b.z);} P operator * (double t, P a) {return P(t * a.x, t * a.y, t * a.z);} double dot(P a, P b) {return a.x * b.x + a.y * b.y + a.z * b.z;} P cross(P a, P b) {return P(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);} int main() { int T; scanf("%d", &T); while(T--) { scanf("%lf%lf%lf", &p1.x, &p1.y, &p1.z); scanf("%lf%lf%lf", &p3.x, &p3.y, &p3.z); scanf("%lf%lf%lf", &p2.x, &p2.y, &p2.z); scanf("%lf%lf%lf", &p4.x, &p4.y, &p4.z); s1 = p3 - p1; s2 = p4 - p2; double t1 = dot(cross(p2 - p1, s2), cross(s1, s2))/dot(cross(s1,s2), cross(s1,s2)); double t2 = dot(cross(p1 - p2, s1), cross(s2, s1))/dot(cross(s2,s1), cross(s2,s1)); P a = p1 + t1 * s1; P b = p2 + t2 * s2; printf("%.6f\n", sqrt(dot(a - b, a - b))); printf("%.6f %.6f %.6f ", a.x, a.y, a.z); printf("%.6f %.6f %.6f\n", b.x, b.y, b.z); } return 0; }
相关文章推荐
- Sublime Text Package Collections
- ActiveMQ 即时通讯服务 浅析
- poj3259 Bellman_ford
- javascript 将数字变为可读取型式
- ios开发--常用的高效开发的宏
- 在开发修改了分支内容之后但是在历史中没有看到开发的提交记录
- 网站RSS开发的初步认识
- java编码setCharacterEncoding---RTFSC
- 如何切换对应分支看提交历史
- javascript【字符串】相关函数
- 转发在Visual Studio 2010/2012/2013/2015上使用C#开发Android/IOS安装包和操作步骤
- IE事件处理程序与其他浏览器之区别
- ORMLite在后台service中进行数据处理
- 文件服务器蓝屏修复全过程分享
- Visual Studio 2015环境搭建
- iOS编程——CGAffineTransform相关函数
- 关于互联网产品经理有哪些经典书籍?
- js 事件绑定的方法
- 字符串中最长的数字子串
- 须弥山菩提树