forked from mpfeifer1/Kattis
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjunk.cpp
118 lines (100 loc) · 2.54 KB
/
junk.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <bits/stdc++.h>
using namespace std;
typedef long double ld;
ld eps = .00001;
struct point {
ld x, y, z;
};
struct junk {
point init;
ld r;
ld dx, dy, dz;
};
ld dist(point p1, point p2) {
ld x = pow(p1.x-p2.x, 2);
ld y = pow(p1.y-p2.y, 2);
ld z = pow(p1.z-p2.z, 2);
return sqrt(x + y + z);
}
point getpoint(junk p, ld t) {
point ret;
ret.x = p.init.x + t*p.dx;
ret.y = p.init.y + t*p.dy;
ret.z = p.init.z + t*p.dz;
return ret;
}
ld ternary(junk ship, junk debris) {
ld lo = 0;
ld hi = 1000;
while(hi - lo > eps) {
//cout << "search: " << lo << " " << hi << endl;
ld diff = (hi - lo) / 3;
ld mi_lo = lo + diff;
point shiplo = getpoint(ship, mi_lo);
point debrislo = getpoint(debris, mi_lo);
ld distlo = dist(shiplo, debrislo);
ld mi_hi = lo + 2 * diff;
point shiphi = getpoint(ship, mi_hi);
point debrishi = getpoint(debris, mi_hi);
ld disthi = dist(shiphi, debrishi);
if(distlo < disthi) {
hi = mi_hi;
}
else {
lo = mi_lo;
}
}
return lo;
}
ld binary(junk ship, junk debris, ld t) {
ld target = ship.r + debris.r;
ld lo = 0;
ld hi = t;
while(hi - lo > eps) {
ld mi = (hi + lo) / 2;
point shipmi = getpoint(ship, mi);
point debrismi = getpoint(debris, mi);
ld disthere = dist(shipmi, debrismi);
if(disthere < target) {
hi = mi;
}
else {
lo = mi;
}
}
return lo;
}
void solve() {
junk ship;
junk debris;
// Read in the ship
cin >> ship.init.x;
cin >> ship.init.y;
cin >> ship.init.z;
cin >> ship.r >> ship.dx >> ship.dy >> ship.dz;
// Read in the debris
cin >> debris.init.x;
cin >> debris.init.y;
cin >> debris.init.z;
cin >> debris.r >> debris.dx >> debris.dy >> debris.dz;
// Ternary search on point when they're closest together
ld t = ternary(ship, debris);
// If they don't touch, print no collision
point shipend = getpoint(ship, t);
point debrisend = getpoint(debris, t);
ld targetdist = ship.r + debris.r;
if(dist(shipend, debrisend) > targetdist + eps) {
cout << "No collision" << endl;
return;
}
// Otherwise, binary search on the initial impact, print answer
ld ans = binary(ship, debris, t);
cout << fixed << setprecision(3) << ans << endl;
}
int main() {
int cases;
cin >> cases;
while(cases--) {
solve();
}
}