- 描述
-
In this problem, you're to calculate the distance between a point P(xp, yp, zp) and a segment (x1, y1, z1) − (x2,y2, z2), in a 3D space, i.e. the minimal distance from P to any point Q(xq, yq, zq) on the segment (a segment is part of a line).
- 输入
-
The first line contains a single integer T (1 ≤ T ≤ 1000), the number of test cases. Each test case is a single line containing 9 integers xp, yp, zp, x1, y1, z1, x2, y2, z2. These integers are all in [-1000,1000].
- 输出
-
For each test case, print the case number and the minimal distance, to two decimal places.
- 样例输入
-
3 0 0 0 0 1 0 1 1 0 1 0 0 1 0 1 1 1 0 -1 -1 -1 0 1 0 -1 0 -1
- 样例输出
-
Case 1: 1.00 Case 2: 0.71 Case 3: 1.00
不满足单调性,所以不能直接二分查找,三分查找。
#include <iostream> #include <cmath> #include <cstdio> using namespace std; const double EPS = 1e-8; struct Node{ double x; double y; double z; }; double Cal(Node p1,Node p2) { return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)+(p1.z-p2.z)*(p1.z-p2.z)); } double Solve(Node p,Node p1,Node p2) { Node mid,midmid; Node left = p1,right = p2; double mid_len,midmid_len; while(Cal(left,right)>EPS) { mid.x = (left.x + right.x) / 2.0; mid.y = (left.y + right.y) / 2.0; mid.z = (left.z + right.z) / 2.0; midmid.x = (mid.x + right.x) / 2.0; midmid.y = (mid.y + right.y) / 2.0; midmid.z = (mid.z + right.z) / 2.0; mid_len = Cal(p, mid); midmid_len = Cal(p, midmid); if (mid_len <= midmid_len) right = midmid; else left = mid; } return Cal(p,left); } int main() { freopen("in.txt","r",stdin); int count = 1; int t; cin>>t; Node p,l,r; while(t--) { cin>>p.x>>p.y>>p.z; cin>>l.x>>l.y>>l.z; cin>>r.x>>r.y>>r.z; printf("Case %d: %.2lf\n",count++,Solve(p,l,r)); } }