http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2896
一道几何模拟题。题意是,两只狗分别在两条折线上运动,已知运动轨迹,以及他们是同时到达折线的末端的。问题是,要求他们运动过程中最大距离与最小距离的差是多少。
表示我十分欣赏这题的做法。估计是我太饿了的缘故,居然看了天都没有想到可以将同时运动转化为相对运动,然后用静态的方法来解决这个动态的问题。如果假设A是不动的,那么这时候,我们只要搞到相对位移就可以解决问题了。
代码如下:
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <set> 5 #include <vector> 6 #include <iostream> 7 #include <algorithm> 8 9 using namespace std; 10 11 #define REP(i, n) for (int i = 0; i < (n); i++) 12 13 struct Point { 14 double x, y; 15 Point() {} 16 Point(double x, double y) : x(x), y(y) {} 17 } ; 18 template<class T> T sqr(T x) { return x * x;} 19 double ptDis(Point a, Point b) { return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));} 20 21 // basic calculations 22 typedef Point Vec; 23 Vec operator + (Vec a, Vec b) { return Vec(a.x + b.x, a.y + b.y);} 24 Vec operator - (Vec a, Vec b) { return Vec(a.x - b.x, a.y - b.y);} 25 Vec operator * (Vec a, double p) { return Vec(a.x * p, a.y * p);} 26 Vec operator / (Vec a, double p) { return Vec(a.x / p, a.y / p);} 27 28 const double eps = 1e-8; 29 int sgn(double x) { return fabs(x) < eps ? 0 : (x < 0 ? -1 : 1);} 30 bool operator < (Point a, Point b) { return a.x < b.x || (a.x == b.x && a.y < b.y);} 31 bool operator == (Point a, Point b) { return sgn(a.x - b.x) == 0 && sgn(a.y - b.y) == 0;} 32 33 double dotDet(Vec a, Vec b) { return a.x * b.x + a.y * b.y;} 34 double vecLen(Vec x) { return sqrt(sqr(x.x) + sqr(x.y));} 35 double angle(Vec a, Vec b) { return acos(dotDet(a, b) / vecLen(a) / vecLen(b));} 36 double crossDet(Vec a, Vec b) { return a.x * b.y - a.y * b.x;} 37 double triArea(Point a, Point b, Point c) { return fabs(crossDet(b - a, c - a));} 38 Vec rotate(Vec x, double rad) { return Vec(x.x * cos(rad) - x.y * sin(rad), x.x * sin(rad) + x.y * cos(rad));} 39 Vec normal(Vec x) { 40 double len = vecLen(x); 41 return Vec(- x.y / len, x.x / len); 42 } 43 44 struct Line { 45 Point s, t; 46 Line() {} 47 Line(Point s, Point t) : s(s), t(t) {} 48 } ; 49 typedef Line Seg; 50 51 bool onSeg(Point x, Point a, Point b) { return sgn(crossDet(a - x, b - x)) == 0 && sgn(dotDet(a - x, b - x)) < 0;} 52 bool onSeg(Point x, Seg s) { return onSeg(x, s.s, s.t);} 53 // 0 : not intersect 54 // 1 : proper intersect 55 // 2 : improper intersect 56 int segIntersect(Point a, Point c, Point b, Point d) { 57 Vec v1 = b - a, v2 = c - b, v3 = d - c, v4 = a - d; 58 int a_bc = sgn(crossDet(v1, v2)); 59 int b_cd = sgn(crossDet(v2, v3)); 60 int c_da = sgn(crossDet(v3, v4)); 61 int d_ab = sgn(crossDet(v4, v1)); 62 if (a_bc * c_da > 0 && b_cd * d_ab > 0) return 1; 63 if (onSeg(b, a, c) && c_da) return 2; 64 if (onSeg(c, b, d) && d_ab) return 2; 65 if (onSeg(d, c, a) && a_bc) return 2; 66 if (onSeg(a, d, b) && b_cd) return 2; 67 return 0; 68 } 69 int segIntersect(Seg a, Seg b) { return segIntersect(a.s, a.t, b.s, b.t);} 70 71 // point of the intersection of 2 lines 72 Point lineIntersect(Point P, Vec v, Point Q, Vec w) { 73 Vec u = P - Q; 74 double t = crossDet(w, u) / crossDet(v, w); 75 return P + v * t; 76 } 77 Point lineIntersect(Line a, Line b) { return lineIntersect(a.s, a.t - a.s, b.s, b.t - b.s);} 78 79 // directed distance 80 double pt2Line(Point x, Point a, Point b) { 81 Vec v1 = b - a, v2 = x - a; 82 return crossDet(v1, v2) / vecLen(v1); 83 } 84 double pt2Line(Point x, Line L) { return pt2Line(x, L.s, L.t);} 85 86 double pt2Seg(Point x, Point a, Point b) { 87 if (a == b) return vecLen(x - a); 88 Vec v1 = b - a, v2 = x - a, v3 = x - b; 89 if (sgn(dotDet(v1, v2)) < 0) return vecLen(v2); 90 if (sgn(dotDet(v1, v3)) > 0) return vecLen(v3); 91 return fabs(crossDet(v1, v2)) / vecLen(v1); 92 } 93 double pt2Seg(Point x, Seg s) { return pt2Seg(x, s.s, s.t);} 94 95 struct Poly { 96 vector<Point> pt; 97 Poly() {} 98 Poly(vector<Point> pt) : pt(pt) {} 99 double area() { 100 double ret = 0.0; 101 int sz = pt.size(); 102 for (int i = 1; i < sz; i++) { 103 ret += crossDet(pt[i], pt[i - 1]); 104 } 105 return fabs(ret / 2.0); 106 } 107 } ; 108 109 /****************** template above *******************/ 110 111 const int N = 55; 112 Point A[N], B[N]; 113 114 int main() { 115 // freopen("in", "r", stdin); 116 int a, b, T; 117 cin >> T; 118 for (int cas = 1; cas <= T; cas++) { 119 cin >> a >> b; 120 for (int i = 0; i < a; i++) cin >> A[i].x >> A[i].y; 121 for (int i = 0; i < b; i++) cin >> B[i].x >> B[i].y; 122 double lenA = 0.0, lenB = 0.0; 123 for (int i = 1; i < a; i++) lenA += ptDis(A[i - 1], A[i]); 124 for (int i = 1; i < b; i++) lenB += ptDis(B[i - 1], B[i]); 125 Point posA = A[0], posB = B[0]; 126 double mn = 1e100, mx = 0.0; 127 int idA = 1, idB = 1; 128 while (idA < a && idB < b) { 129 double disA = ptDis(posA, A[idA]); 130 double disB = ptDis(posB, B[idB]); 131 double minTime = min(disA / lenA, disB / lenB); 132 Vec dirA = (A[idA] - posA) * minTime * lenA / disA; // displacement of A 133 Vec dirB = (B[idB] - posB) * minTime * lenB / disB; // displacement of B 134 mn = min(mn, pt2Seg(posA, posB, posB + dirB - dirA)); // see A as static, so it is just that B is moving 135 mx = max(mx, max(ptDis(posA, posB), ptDis(posA, posB + dirB - dirA))); 136 posA = posA + dirA; 137 posB = posB + dirB; 138 if (posA == A[idA]) idA++; 139 if (posB == B[idB]) idB++; 140 } 141 printf("Case %d: %.f\n", cas, mx - mn); 142 } 143 return 0; 144 }
——written by Lyon