又是搞了一个晚上啊!!!
总算是得到一个教训,误差总是会有的,不过需要用方法排除误差。想这题才几分钟,敲这题才半个钟,debug就用了一个晚上了!TAT
有一定几何基础的很容易想到这里的碰撞一定是其中一个顶点撞到另一个三角形的边上,于是就可以暴力枚举每一个顶点的最先碰撞的时间。注意的是,求直线相交以后,判交点是否在线段内,对于1e7的数据,千万不要判点在线上!TAT 因为已经知道是交点了,只要判断是不是在两点之间就好了。
代码如下:(把onseg改少了一个判断就过了)
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 #include <cmath> 6 7 using namespace std; 8 9 const double EPS = 1e-8; 10 const double FINF = 1e100; 11 template<class T> T sqr(T x) { return x * x;} 12 inline int sgn(double x) { return (x > EPS) - (x < -EPS);} 13 14 struct Point { 15 double x, y; 16 Point() {} 17 Point(double x, double y) : x(x), y(y) {} 18 Point operator + (Point a) { return Point(x + a.x, y + a.y);} 19 Point operator - (Point a) { return Point(x - a.x, y - a.y);} 20 Point operator * (double p) { return Point(x * p, y * p);} 21 Point operator / (double p) { return Point(x / p, y / p);} 22 } ; 23 24 inline double cross(Point a, Point b) { return a.x * b.y - a.y * b.x;} 25 inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y;} 26 inline double veclen(Point x) { return sqrt(dot(x, x));} 27 inline Point vecunit(Point x) { return x / veclen(x);} 28 29 struct Line { 30 Point s, t; 31 Line() {} 32 Line(Point s, Point t) : s(s), t(t) {} 33 Point vec() { return t - s;} 34 Point point(double p) { return s + vec() * p;} 35 } ; 36 37 inline bool onseg(Point x, Point a, Point b) { return sgn(dot(a - x, b - x)) <= 0;} 38 inline Point llint(Line a, Line b) { return a.point(cross(b.vec(), a.s - b.s) / cross(a.vec(), b.vec()));} 39 40 Point tri[5][8], v[5]; 41 42 double work(int a, int b) { 43 double ret = FINF; 44 Point vec = v[a] - v[b]; 45 for (int i = 0; i < 3; i++) { 46 for (int j = 0; j < 3; j++) { 47 if (sgn(cross(vec, tri[b][j] - tri[b][j + 1])) == 0) continue; 48 Point ip = llint(Line(tri[a][i], tri[a][i] + vec), Line(tri[b][j], tri[b][j + 1])); 49 if (!onseg(ip, tri[b][j], tri[b][j + 1])) continue; 50 Point dir = ip - tri[a][i]; 51 if (sgn(dot(dir, vec)) < 0) continue; 52 ret = min(ret, veclen(dir) / veclen(vec)); 53 } 54 } 55 return ret; 56 } 57 58 inline double work() { return min(work(0, 1), work(1, 0));} 59 60 int main() { 61 //freopen("in", "r", stdin); 62 int T; 63 cin >> T; 64 while (T--) { 65 for (int i = 0; i < 2; i++) { 66 for (int j = 0; j < 3; j++) cin >> tri[i][j].x >> tri[i][j].y; 67 tri[i][3] = tri[i][0]; 68 cin >> v[i].x >> v[i].y; 69 } 70 double ans = work(); 71 //cout << work(0, 1) << ' ' << work(1, 0) << endl; 72 if (ans >= FINF) puts("NO COLLISION"); 73 else printf("%.12f ", ans); 74 } 75 return 0; 76 }
——written by Lyon