• LA 4676 Geometry Problem (几何)


    ACM-ICPC Live Archive

      又是搞了一个晚上啊!!!

      总算是得到一个教训,误差总是会有的,不过需要用方法排除误差。想这题才几分钟,敲这题才半个钟,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 }
    View Code

    ——written by Lyon

  • 相关阅读:
    从Android Launcher源码学习自定义标签
    Android的TextView使用Html来处理图片显示、字体样式、超链接等
    mysql的字符串函数
    JavaScript求当月天数
    keycode对照表
    Android onMeasure方法介绍
    SpannableString或SpannableStringBuilder以及string.xml文件中的整型和string型代替
    表单的内容用WORD形式保存
    在LOTUS NOTES 中通过ODBC访问关系数据库的方法
    通过LEI技术实现NOTES与SQL2000数据交换
  • 原文地址:https://www.cnblogs.com/LyonLys/p/LA_4676_Lyon.html
Copyright © 2020-2023  润新知