首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

POJ 1755 Triathlon(半平递给解不等式)

2012-09-22 
POJ 1755 Triathlon(半平面交解不等式)转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/deta

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

转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526       by---cxlove

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

我们假设三项的路程分别人X,Y,Z。

比较其中的两个人。A的时间为X / U1+Y / V1+Z / W1     B的时间为X / U2 +Y / V2 +Z / W2

如果A想要获胜妈,X / U1+Y / V1+Z / W1 - X / U2 +Y / V2 +Z / W2 < 0

由于我写的是顺时针的,所以把不等式变个号。这里一定要注意,小于0大于0和顺时针逆时针的对应关系

这个不等式还是有3个未知数。显然用三维就太麻烦了。由于我们最终不需要求出X,Y,Z具体为多少,而且Z>0,所以把不等式两边同时除以Z,则把X/Z看成一个未知量,Y/Z看成另外一个。

问题转化成一系列的不等式是否为解,而且注意条件X>0 Y>0

那么可以设立一个初始范围,(0,0)(0,inf)(inf,inf)(inf,0)

然后通过两个人的参数,求出AX+BY+C>0,通过半平面交解决,最终判断面积是否为0

有几个地方需要注意:

这题要求的精度很高,大家一味的说需要1e-16,其实不然,1e-8也过了。主要是中间的处理细节,对于1/U1-1/U2,普通的处理是需要两次除法,精度严重受损,可以改成(U2-U1)/(U1*U2)。

另外 就是特判,题目要求是不能并列,所以最终结果是大于0才行。而且如果遇到A==0&&B==0&&C<=0说明不等式无解,直接返回

#include<iostream>#include<fstream>#include<iomanip>#include<cstdio>#include<cstring>#include<algorithm>#include<cstdlib>#include<cmath>#include<set>#include<map>#include<queue>#include<stack>#include<string>#include<vector>#include<sstream>#include<cassert>#define LL long long#define eps 1e-8#define inf 1<<28#define zero(a) fabs(a)<epsusing namespace std;struct Point{    double x,y;}p[1505],tp[1505],q[1505];struct Node{    double u,v,w;}z[105];double xmul(Point p0,Point p1,Point p2){    return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);}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;}double Get_area(Point p[],int n){    double area=0;    for(int i=2;i<n;i++)        area+=xmul(p[1],p[i],p[i+1]);    return -area/2.0;}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)                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;}int slove(int n,int idx){    p[1].x=0;p[1].y=0;    p[2].x=0;p[2].y=inf;    p[3].x=inf;p[3].y=inf;    p[4].x=inf;p[4].y=0;    p[0]=p[4];p[5]=p[1];    int cnt=4;    for(int i=0;i<n;i++){        if(i==idx) continue;        double a,b,c;        a=(z[idx].u-z[i].u)/(z[idx].u*z[i].u);        b=(z[idx].v-z[i].v)/(z[idx].v*z[i].v);        c=(z[idx].w-z[i].w)/(z[idx].w*z[i].w);        if(a==0&&b==0&&c<eps) return 0;        Cut(a,b,c,p,cnt);    }    return !zero(Get_area(p,cnt));}int main(){    int n;    while( scanf("%d",&n)!=EOF){        for(int i=0;i<n;i++)            scanf("%lf%lf%lf",&z[i].u,&z[i].v,&z[i].w);        for(int i=0;i<n;i++)            puts(slove(n,i)?"Yes":"No");    }    return 0;}



热点排行