POJ 1755 Triathlon (半平面交解不等式)

Triathlon
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 6013 Accepted: 1515

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

 

大年30了。。。还在苦苦做题。。。。o(︶︿︶)o 唉。。。。。

 

题意:铁人三项,每个人在某一项中有确定的速度,裁判可以决定某一项比赛的路程为多少,问对于某个人,是否存在一种安排能使他拿到第一,而且不能是并列。

 

思路:比如A的时间为 T1 = x/v1+y/u1+z/w1 , B的时间为 T2 = x/v2+y/u2+z/w2  那么当A时间小于B的时候有等式 T1 - T2 < 0 ,为了2个保持未知数化,都除Z简过后为(1/v1-1/v2)*x+(1/u1-1/u2)*y+(1/w1-1/w2)<0  a,b,c 都有了,最后要对所有人列一个等式,看有没有解,也就是凸包切割结果看有没有核,由于不等式是小于号,最后的凸包的核必须是有面积的。精度竟然要1e-18,大了就错了。。但有人1e-8也过了。。郁闷。

 

代码:

 

#include<stdio.h>
#include<math.h>
#include<map>
#include<iostream>
#include<string.h>
using namespace std;
const int inf = 1 << 29;
const int N = 1505;
const double eps = 1e-18;
const double PI = acos(-1.0);
int sgn(double x)
{
    if(fabs(x) < eps)return 0;
    if(x < 0)return -1;
    else return 1;
}
struct Point
{
    double x,y;
    Point() {}
    Point(double _x,double _y)
    {
        x = _x;
        y = _y;
    }
    Point operator -(const Point &b)const
    {
        return Point(x - b.x,y - b.y);
    }
    double operator ^(const Point &b)const
    {
        return x*b.y - y*b.x;
    }
    double operator *(const Point &b)const
    {
        return x*b.x + y*b.y;
    }
};
//计算多边形面积
double CalcArea(Point p[],int n)
{
    double res = 0;
    for(int i = 0; i < n; i++)
        res += (p[i]^p[(i+1)%n]);
    return fabs(res/2);
}
//通过两点,确定直线方程
void Get_equation(Point p1,Point p2,double &a,double &b,double &c)
{
    a = p2.y - p1.y;
    b = p1.x - p2.x;
    c = p2.x*p1.y - p1.x*p2.y;
}
//求交点
Point Intersection(Point p1,Point p2,double a,double b,double c)
{
    double u = fabs(a*p1.x + b*p1.y + c);
    double v = fabs(a*p2.x + b*p2.y + c);
    Point t;
    t.x = (p1.x*v + p2.x*u)/(u+v);
    t.y = (p1.y*v + p2.y*u)/(u+v);
    return t;
}
Point tp[N],p[N],q[N];
void Cut(double a,double b,double c,Point p[],int &cnt)
{
    int tmp = 0;
    for(int i = 1; i <= cnt; i++)
    {
//当前点在左侧,逆时针的点
        if(a*p[i].x + b*p[i].y + c < eps)tp[++tmp] = p[i];
        else
        {
            if(a*p[i-1].x + b*p[i-1].y + c < -eps)//如果p[i-1]在直线的左侧的话,
                
//则将p[i],p[i-1]形成的直线与已知直线的交点作为核的一个顶点(这样的话,由于精度的问题,核的面积可能会有所减少)
                tp[++tmp] = Intersection(p[i-1],p[i],a,b,c);
            if(a*p[i+1].x + b*p[i+1].y + c < -eps)
                tp[++tmp] = Intersection(p[i],p[i+1],a,b,c);
        }
    }
    for(int i = 1; i <= tmp; i++)
        p[i] = tp[i];
    p[0] = p[tmp];
    p[tmp+1] = p[1];
    cnt = tmp;
}
double dist(Point a,Point b)
{
    return sqrt((a-b)*(a-b));
}
void Change_dir(Point p[],int n)
{
    for(int i=1; i<=n/2; i++)
        swap(p[i],p[n+1-i]);
}
struct node
{
    double v,u,w;
} z[N];
bool solve(int n,int id)
{
    p[1] = Point(0,0);
    p[2] = Point(inf,0);
    p[3] = Point(inf,inf);
    p[4] = Point(0,inf);
    p[0] = p[4];
    p[5] = p[1];
    int cnt = 4;
    for(int i=1; i<=n; i++)
    {
        if(i==id)continue;
        double a,b,c;
        a=(z[i].v-z[id].v)/(z[id].v*z[i].v);//a*x+b*y+c<0
        b=(z[i].u-z[id].u)/(z[id].u*z[i].u);
        c=(z[i].w-z[id].w)/(z[id].w*z[i].w);
        if(sgn(a) == 0 && sgn(b) == 0 && sgn(c) >= 0)return false;
        Cut(a,b,c,p,cnt);
    }
    if(sgn(CalcArea(p,cnt)) == 0)return false;
    else return true;
}
int main()
{
    //freopen("in.txt","r",stdin);
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1; i<=n; i++)
            scanf("%lf%lf%lf",&z[i].v,&z[i].u,&z[i].w);
        for(int i=1; i<=n; i++)
            puts(solve(n,i)?"Yes":"No");
    }
    return 0;
}
View Code

 

posted @ 2015-02-18 18:34  Doli  阅读(140)  评论(0)    收藏  举报