poj 1755 Triathlon(半平面交应用)

Triathlon
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 3451   Accepted: 876

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.

Sample Input

9
10 2 6
10 7 3
5 6 7
3 2 7
6 2 6
3 5 7
8 4 6
10 4 2
1 8 7

Sample Output

Yes
Yes
Yes
No
No
No
Yes
No
Yes

Source

Northeastern Europe 2000

题目:http://poj.org/problem?id=1755

题意:有n个人参加三项比赛,你作为一个裁判可以随意调整三个赛段的距离(都大于0),问是否能调整使得指定的选手获胜

分析:这题主要是提前不小心看到别人的题解了= =

首先获胜者只有一个,假设赛段分别为a,b,c,则有a / vi + b / ui + c / wi < a / vj + b / uj + c / wj (0<j<n,  j!=i ) ,由于距离都大于一,我们可以这样转换,

a/c * (1/vi-1/vj) + b/c * (1/ui +1/uj) + (1/wi-1/wj)<0这样的不等式,然后用半平面表示这些不等式,求半平面交的面积是否大于0即可

注意:

1.所有距离必须大于0,所以要假设一个第一象限的限制,自己加个巨大的正方形进去就行

2.构造直线ax+by+c=0时注意 a 和 b同时为0的情况,直线转半平面的情况要讨论清楚

3.这题大家都说精度要到 1e-16,尽管我的代码也是这样,我下载数据后调试才AC的,调试的时候发现就两组数据会出错

一组要求不能直接写面积>0,一组要求面积大于eps的那个数不能太大

而1e-16刚好是介于两者之间了,比赛的话,肯定是过不了了,看来我的算法精度不够的样子啊


代码:

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int mm=111;
const double eps=1e-16;
typedef double diy;
struct point
{
    diy x,y;
    point(){}
    point(diy _x,diy _y):x(_x),y(_y){}
}g[mm];
point Vector(point s,point t)
{
    return point(t.x-s.x,t.y-s.y);
}
diy CrossProduct(point P,point Q)
{
    return P.x*Q.y-P.y*Q.x;
}
diy MultiCross(point P,point Q,point R)
{
    return CrossProduct(Vector(Q,P),Vector(Q,R));
}
struct halfPlane
{
    point s,t;
    diy angle;
    halfPlane(){}
    halfPlane(point _s,point _t){s=_s,t=_t,angle=atan2(t.y-s.y,t.x-s.x);}
}hp[mm],q[mm];
point Intersection(halfPlane P,halfPlane Q)
{
    diy a1=CrossProduct(Vector(P.s,Q.t),Vector(P.s,Q.s));
    diy a2=CrossProduct(Vector(P.t,Q.s),Vector(P.t,Q.t));
    return point((P.s.x*a2+P.t.x*a1)/(a1+a2),(P.s.y*a2+P.t.y*a1)/(a1+a2));
}
bool IsParallel(halfPlane P,halfPlane Q)
{
    return fabs(CrossProduct(Vector(P.s,P.t),Vector(Q.s,Q.t)))<eps;
}
bool cmp(halfPlane P,halfPlane Q)
{
    if(fabs(P.angle-Q.angle)<eps)
        return MultiCross(P.s,P.t,Q.s)>0;
    return P.angle<Q.angle;
}
void HalfPlaneIntersect(int n,int &m)
{
    sort(hp,hp+n,cmp);
    int i,l=0,r=1;
    for(m=i=1;i<n;++i)
        if(hp[i].angle-hp[i-1].angle>eps)hp[m++]=hp[i];
    n=m;
    m=0;
    q[0]=hp[0],q[1]=hp[1];
    for(i=2;i<n;++i)
    {
        if(IsParallel(q[r],q[r-1])||IsParallel(q[l],q[l+1]))return;
        while(l<r&&MultiCross(hp[i].s,hp[i].t,Intersection(q[r],q[r-1]))>0)--r;
        while(l<r&&MultiCross(hp[i].s,hp[i].t,Intersection(q[l],q[l+1]))>0)++l;
        q[++r]=hp[i];
    }
    while(l<r&&MultiCross(q[l].s,q[l].t,Intersection(q[r],q[r-1]))>0)--r;
    while(l<r&&MultiCross(q[r].s,q[r].t,Intersection(q[l],q[l+1]))>0)++l;
    q[++r]=q[l];
    for(i=l;i<r;++i)
        g[m++]=Intersection(q[i],q[i+1]);
}
double v[mm],u[mm],w[mm];
int i,n;
bool ok(int o)
{
    double a,b,c,area;
    int i,m=0,t;
    for(i=0;i<n;++i)
        if(i!=o)
        {
            a=(v[i]-v[o])/(v[o]*v[i]);
            b=(u[i]-u[o])/(u[o]*u[i]);
            c=(w[i]-w[o])/(w[o]*w[i]);
            if(fabs(a)<eps&&fabs(b)<eps)
            {
                if(w[i]>=w[o])return 0;
                continue;
            }
            if(fabs(a)<eps)
                hp[m++]=halfPlane(point(b<0?-1:1,-c/b),point(b<0?1:-1,-c/b));
            else if(fabs(b)<eps)
                hp[m++]=halfPlane(point(-c/a,a<0?1:-1),point(-c/a,a<0?-1:1));
            else if(b<0)
                hp[m++]=halfPlane(point(0,-c/b),point(1,-(a+c)/b));
            else hp[m++]=halfPlane(point(1,-(a+c)/b),point(0,-c/b));
        }
    hp[m++]=halfPlane(point(0,0),point(1e8,0));
    hp[m++]=halfPlane(point(1e6,0),point(1e6,1e6));
    hp[m++]=halfPlane(point(1e6,1e6),point(0,1e6));
    hp[m++]=halfPlane(point(0,1e6),point(0,0));
    HalfPlaneIntersect(m,t);
    area=0;
    g[t]=g[0];
    for(i=0;i<t;++i)
        area+=CrossProduct(g[i],g[i+1]);
    return fabs(area)>eps;
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(i=0;i<n;++i)
            scanf("%lf%lf%lf",&v[i],&u[i],&w[i]);
        for(i=0;i<n;++i)
            puts(ok(i)?"Yes":"No");
    }
    return 0;
}



你可能感兴趣的:(poj 1755 Triathlon(半平面交应用))