zoukankan      html  css  js  c++  java
  • POJ 1755 Triathlon(线性规划の半平面交)

    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. 

    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 }
    View Code
  • 相关阅读:
    Trie树与AC自动机
    学习强国答题小程序
    小程序如何引导添加个人微信号
    成语答题赚小程序里面涉及到金额的小数计算问题
    答题小程序v2.0
    活动抽奖小程序
    抽奖小程序分享
    抽奖小程序结果页设计
    抽奖小程序数据库设计
    答题活动小程序复盘记录
  • 原文地址:https://www.cnblogs.com/oyking/p/3417118.html
Copyright © 2011-2022 走看看