Description
Triathlon is an athletic contest consisting of three consecutive sections that should be completed as fast as possible as a whole. The first section is swimming, the second section is riding bicycle and the third one is running.
The speed of each contestant in all three sections is known. The judge can choose the length of each section arbitrarily provided that no section has zero length. As a result sometimes she could choose their lengths in such a way that some particular contestant would win the competition.
The speed of each contestant in all three sections is known. The judge can choose the length of each section arbitrarily provided that no section has zero length. As a result sometimes she could choose their lengths in such a way that some particular contestant would win the competition.
Input
The first line of the input file contains integer number N (1 <= N <= 100), denoting the number of contestants. Then N lines follow, each line contains three integers Vi, Ui and Wi (1 <= Vi, Ui, Wi <= 10000), separated by spaces, denoting the speed of ith contestant in each section.
Output
For every contestant write to the output file one line, that contains word "Yes" if the judge could choose the lengths of the sections in such a way that this particular contestant would win (i.e. she is the only one who would come first), or word "No" if this is impossible.
题目大意:铁人三项中,给出每个人玩铁人三项的速度,问能否通过调整这些比赛的距离(比如100米改成200米),使某个人获胜。
思路:设铁人三项的长度为x、y、z,x + y + z = 1,那么z = 1 - x - y。对于某个人cur,要满足对所有的人 i ,x / spd1[cur] + y / spd2[cur] + z / spd3[cur] < x / spd1[i] + y / spd2[i] + z / spd3[i]。
化简可得(1/spd1[i] - 1/spd1[cur] - 1/spd3[i] + 1/spd3[cur])*x + (1/spd2[i] - 1/spd2[cur] - 1/spd3[i] + 1/spd3[cur])*y + (1/spd3[i] - 1/spd3[cur]) > 0。
然后建立x+y<1和x>0,y>0,与上面的不等式,求是否存在可行域。求半平面交看有否可行域即可。
正在做模板,想办法把ax+by+c>0化成了两点式(见代码,要分类讨论),再做半平面交,我这种写法要EPS=1e-16才能过,丢的精度太多了。
代码(94MS):
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 8 const int MAXN = 110; 9 const double EPS = 1e-16; 10 const double PI = acos(-1.0);//3.14159265358979323846 11 const double INF = 1; 12 13 inline int sgn(double x) { 14 return (x > EPS) - (x < -EPS); 15 } 16 17 struct Point { 18 double x, y, ag; 19 Point() {} 20 Point(double x, double y): x(x), y(y) {} 21 void read() { 22 scanf("%lf%lf", &x, &y); 23 } 24 bool operator == (const Point &rhs) const { 25 return sgn(x - rhs.x) == 0 && sgn(y - rhs.y) == 0; 26 } 27 bool operator < (const Point &rhs) const { 28 if(y != rhs.y) return y < rhs.y; 29 return x < rhs.x; 30 } 31 Point operator + (const Point &rhs) const { 32 return Point(x + rhs.x, y + rhs.y); 33 } 34 Point operator - (const Point &rhs) const { 35 return Point(x - rhs.x, y - rhs.y); 36 } 37 Point operator * (const int &b) const { 38 return Point(x * b, y * b); 39 } 40 Point operator / (const int &b) const { 41 return Point(x / b, y / b); 42 } 43 double length() { 44 return sqrt(x * x + y * y); 45 } 46 Point unit() { 47 return *this / length(); 48 } 49 void print() { 50 printf("%.10f %.10f ", x, y); 51 } 52 }; 53 typedef Point Vector; 54 55 double dist(const Point &a, const Point &b) { 56 return (a - b).length(); 57 } 58 59 double cross(const Point &a, const Point &b) { 60 return a.x * b.y - a.y * b.x; 61 } 62 //ret >= 0 means turn left 63 double cross(const Point &sp, const Point &ed, const Point &op) { 64 return sgn(cross(sp - op, ed - op)); 65 } 66 67 double area(const Point& a, const Point &b, const Point &c) { 68 return fabs(cross(a - c, b - c)) / 2; 69 } 70 //counter-clockwise 71 Point rotate(const Point &p, double angle, const Point &o = Point(0, 0)) { 72 Point t = p - o; 73 double x = t.x * cos(angle) - t.y * sin(angle); 74 double y = t.y * cos(angle) + t.x * sin(angle); 75 return Point(x, y) + o; 76 } 77 78 struct Seg { 79 Point st, ed; 80 double ag; 81 Seg() {} 82 Seg(Point st, Point ed): st(st), ed(ed) {} 83 void read() { 84 st.read(); ed.read(); 85 } 86 void makeAg() { 87 ag = atan2(ed.y - st.y, ed.x - st.x); 88 } 89 }; 90 typedef Seg Line; 91 92 //ax + by + c > 0 93 Line buildLine(double a, double b, double c) { 94 if(sgn(a) == 0 && sgn(b) == 0) return Line(Point(sgn(c) > 0 ? -1 : 1, INF), Point(0, INF)); 95 if(sgn(a) == 0) return Line(Point(sgn(b), -c/b), Point(0, -c/b)); 96 if(sgn(b) == 0) return Line(Point(-c/a, 0), Point(-c/a, sgn(a))); 97 if(b < 0) return Line(Point(0, -c/b), Point(1, -(a + c) / b)); 98 else return Line(Point(1, -(a + c) / b), Point(0, -c/b)); 99 } 100 101 void moveRight(Line &v, double r) { 102 double dx = v.ed.x - v.st.x, dy = v.ed.y - v.st.y; 103 dx = dx / dist(v.st, v.ed) * r; 104 dy = dy / dist(v.st, v.ed) * r; 105 v.st.x += dy; v.ed.x += dy; 106 v.st.y -= dx; v.ed.y -= dx; 107 } 108 109 bool isOnSeg(const Seg &s, const Point &p) { 110 return (p == s.st || p == s.ed) || 111 (((p.x - s.st.x) * (p.x - s.ed.x) < 0 || 112 (p.y - s.st.y) * (p.y - s.ed.y) < 0) && 113 sgn(cross(s.ed, p, s.st) == 0)); 114 } 115 116 bool isIntersected(const Point &s1, const Point &e1, const Point &s2, const Point &e2) { 117 return (max(s1.x, e1.x) >= min(s2.x, e2.x)) && 118 (max(s2.x, e2.x) >= min(s1.x, e1.x)) && 119 (max(s1.y, e1.y) >= min(s2.y, e2.y)) && 120 (max(s2.y, e2.y) >= min(s1.y, e1.y)) && 121 (cross(s2, e1, s1) * cross(e1, e2, s1) >= 0) && 122 (cross(s1, e2, s2) * cross(e2, e1, s2) >= 0); 123 } 124 125 bool isIntersected(const Seg &a, const Seg &b) { 126 return isIntersected(a.st, a.ed, b.st, b.ed); 127 } 128 129 bool isParallel(const Seg &a, const Seg &b) { 130 return sgn(cross(a.ed - a.st, b.ed - b.st)) == 0; 131 } 132 133 //return Ax + By + C =0 's A, B, C 134 void Coefficient(const Line &L, double &A, double &B, double &C) { 135 A = L.ed.y - L.st.y; 136 B = L.st.x - L.ed.x; 137 C = L.ed.x * L.st.y - L.st.x * L.ed.y; 138 } 139 //point of intersection 140 Point operator * (const Line &a, const Line &b) { 141 double A1, B1, C1; 142 double A2, B2, C2; 143 Coefficient(a, A1, B1, C1); 144 Coefficient(b, A2, B2, C2); 145 Point I; 146 I.x = - (B2 * C1 - B1 * C2) / (A1 * B2 - A2 * B1); 147 I.y = (A2 * C1 - A1 * C2) / (A1 * B2 - A2 * B1); 148 return I; 149 } 150 151 bool isEqual(const Line &a, const Line &b) { 152 double A1, B1, C1; 153 double A2, B2, C2; 154 Coefficient(a, A1, B1, C1); 155 Coefficient(b, A2, B2, C2); 156 return sgn(A1 * B2 - A2 * B1) == 0 && sgn(A1 * C2 - A2 * C1) == 0 && sgn(B1 * C2 - B2 * C1) == 0; 157 } 158 159 struct Poly { 160 int n; 161 Point p[MAXN];//p[n] = p[0] 162 void init(Point *pp, int nn) { 163 n = nn; 164 for(int i = 0; i < n; ++i) p[i] = pp[i]; 165 p[n] = p[0]; 166 } 167 double area() { 168 if(n < 3) return 0; 169 double s = p[0].y * (p[n - 1].x - p[1].x); 170 for(int i = 1; i < n; ++i) 171 s += p[i].y * (p[i - 1].x - p[i + 1].x); 172 return s / 2; 173 } 174 }; 175 176 void Graham_scan(Point *p, int n, int *stk, int &top) {//stk[0] = stk[top] 177 sort(p, p + n); 178 top = 1; 179 stk[0] = 0; stk[1] = 1; 180 for(int i = 2; i < n; ++i) { 181 while(top && cross(p[i], p[stk[top]], p[stk[top - 1]]) >= 0) --top; 182 stk[++top] = i; 183 } 184 int len = top; 185 stk[++top] = n - 2; 186 for(int i = n - 3; i >= 0; --i) { 187 while(top != len && cross(p[i], p[stk[top]], p[stk[top - 1]]) >= 0) --top; 188 stk[++top] = i; 189 } 190 } 191 //use for half_planes_cross 192 bool cmpAg(const Line &a, const Line &b) { 193 if(sgn(a.ag - b.ag) == 0) 194 return sgn(cross(b.ed, a.st, b.st)) < 0; 195 return a.ag < b.ag; 196 } 197 //clockwise, plane is on the right 198 bool half_planes_cross(Line *v, int vn, Poly &res, Line *deq) { 199 int i, n; 200 sort(v, v + vn, cmpAg); 201 for(i = n = 1; i < vn; ++i) { 202 if(sgn(v[i].ag - v[i-1].ag) == 0) continue; 203 v[n++] = v[i]; 204 } 205 int head = 0, tail = 1; 206 deq[0] = v[0], deq[1] = v[1]; 207 for(i = 2; i < n; ++i) { 208 if(isParallel(deq[tail - 1], deq[tail]) || isParallel(deq[head], deq[head + 1])) 209 return false; 210 while(head < tail && sgn(cross(v[i].ed, deq[tail - 1] * deq[tail], v[i].st)) > 0) 211 --tail; 212 while(head < tail && sgn(cross(v[i].ed, deq[head] * deq[head + 1], v[i].st)) > 0) 213 ++head; 214 deq[++tail] = v[i]; 215 } 216 while(head < tail && sgn(cross(deq[head].ed, deq[tail - 1] * deq[tail], deq[head].st)) > 0) 217 --tail; 218 while(head < tail && sgn(cross(deq[tail].ed, deq[head] * deq[head + 1], deq[tail].st)) > 0) 219 ++head; 220 if(tail <= head + 1) return false; 221 res.n = 0; 222 for(i = head; i < tail; ++i) 223 res.p[res.n++] = deq[i] * deq[i + 1]; 224 res.p[res.n++] = deq[head] * deq[tail]; 225 res.n = unique(res.p, res.p + res.n) - res.p; 226 res.p[res.n] = res.p[0]; 227 return true; 228 } 229 230 /*******************************************************************************************/ 231 232 Poly poly; 233 Line line[MAXN], deq[MAXN]; 234 double a[MAXN], b[MAXN], c[MAXN]; 235 char str[10]; 236 int n, m; 237 238 double calc(double x, double y) { 239 return (y - x) / (x * y); 240 } 241 242 bool check(int cur) { 243 n = 0; 244 line[n++] = buildLine(-1, -1, INF); line[n - 1].makeAg(); 245 line[n++] = buildLine(1, 0, 0); line[n - 1].makeAg(); 246 line[n++] = buildLine(0, 1, 0); line[n - 1].makeAg(); 247 for(int i = 0; i < m; ++i) { 248 if(i == cur) continue; 249 line[n++] = buildLine(calc(a[i], a[cur]) + calc(c[cur], c[i]), calc(b[i], b[cur]) + calc(c[cur], c[i]), INF * calc(c[i], c[cur])); 250 line[n - 1].makeAg(); 251 //printf("%.10f %.10f ", calc(a[i], a[cur]) + calc(c[cur], c[i]), calc(b[i], b[cur]) + calc(c[cur], c[i])), line[n - 1].st.print(), line[n - 1].ed.print(); 252 } 253 bool flag = half_planes_cross(line, n, poly, deq); 254 return flag && sgn(poly.area()); 255 } 256 257 int main() { 258 scanf("%d", &m); 259 for(int i = 0; i < m; ++i) scanf("%lf%lf%lf", &a[i], &b[i], &c[i]); 260 for(int i = 0; i < m; ++i) 261 if(check(i)) puts("Yes"); 262 else puts("No"); 263 }