版权声明:转载注明下出处就行了。 https://blog.csdn.net/LJD201724114126/article/details/84587054
题目链接:哆啦A梦传送门
参考链接:https://blog.csdn.net/acm_cxlove/article/details/7883370
题目:铁人三项,每个人在某一项中有确定的速度,裁判可以决定某一项比赛的路程为多少,问对于某个人,是否存在一种安排能使他拿到第一,而且不能是并列。
题解:我们假设三项的路程分别人X,Y,Z。
A的时间为X / U1+Y / V1+Z / W1 B的时间为X / U2 +Y / V2 +Z / W2
如果A想要获胜妈, X / U2 +Y / V2 +Z / W2 - (X / U1+Y / V1+Z / W1)>0
故,同理,b,c也一样求,因为我们不需要求出变量X,Y,Z的值,而且Z>0,所以把不等式两边同时除以Z,则把X/Z看成一个未知量,Y/Z看成另外一个。
注意下:A==0&&B==0&&C<=0说明不等式无解,直接返回。
还有精度问题:我是弄到1e-18才A的,1e-8,不行。
切割半平面时,还有一个细节,不是很懂,就是为什么要>-esp,而不是>=esp,以后再处理。
还注意一点的是:顺时针是大于0,逆时针是小于0,例如:(0,0),(1,2) 顺时针是 2*x-y=0,逆时针是 -2*x+y=0。
///点是顺时针存储的
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=1510;
#define INF 1<<28;
struct point{
double x,y;
point(){}
point(double _x,double _y){
x=_x;y=_y;
}
};
struct node{
double u,v,w;
};
struct LINE{
point s,t;
LINE(){}
LINE(point _s,point _t){
s=_s;t=_t;
}
};
point operator + (point a,point b) { return point(a.x+b.x,a.y+b.y);}
point operator - (point a,point b) { return point(a.x-b.x,a.y-b.y);}
point operator * (point a,double p) { return point(a.x*p,a.y*p);}
point operator / (point a,double p) { return point(a.x/p,a.y/p);}
const double esp=1e-18;
int dcmp(double x){
if(fabs(x)<esp) return 0;
else return x<0?-1:1;
}
bool operator < (const point &a,const point &b){
return dcmp(a.x-b.x)<0||(dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)<0);
}
bool operator == (const point &a,const point &b){
return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
node poly[maxn]; ///记录最开始的多边形
point q[maxn]; ///临时保存新切割的多边形
point p[maxn]; ///保存新切割出的多边形
int n,m;
double a,b,c;
void getline(point P,point Q)///获取直线ax+by+c==0
{
a=Q.y-P.y;
b=P.x-Q.x;
c=P.y*Q.x-P.x*Q.y;
}
double Cross(point a,point b) { return a.x*b.y-a.y*b.x;}
point Getlinenode(point p1,point p2) ///获取直线ax+by+c==0 和点p1和p2所连直线的交点
{
double u=fabs(a*p1.x+b*p1.y+c);
double v=fabs(a*p2.x+b*p2.y+c);
point ans;
ans.x=(p1.x*v+p2.x*u)/(u+v);
ans.y=(p1.y*v+p2.y*u)/(u+v);
return ans;
}
void cut(point p[],int &cnt ) ///用直线ax+by+c==0切割多边形
{
int tmp=0;
for(int i=1;i<=cnt;i++)
{
///题目是顺时钟给出点的,所以一个点在直线右边的话,那么带入值就会大于等于0
if(a*p[i].x+b*p[i].y+c>-esp) ///这里>-esp,还不是很懂,为什么不是>=esp
q[++tmp]=p[i]; ///说明这个点还在切割后的多边形内,将其保留
else{
///该点不在多边形内,但是它和它相邻的点构成直线与ax+by+c==0所构成的交点可能在新切割出的多边形内,
if(a*p[i-1].x+b*p[i-1].y+c>esp)///所以保留交点
q[++tmp]=Getlinenode(p[i-1],p[i]);
if(a*p[i+1].x+b*p[i+1].y+c>esp)
q[++tmp]=Getlinenode(p[i+1],p[i]);
}
}
for(int i=1;i<=tmp;i++)
p[i]=q[i];
p[0]=q[tmp];
p[tmp+1]=q[1];
cnt=tmp;
}
int solve(int id)
{
p[1].x=0;p[1].y=0; ///初始化平面
p[2].x=0;p[2].y=INF;
p[3].x=INF;p[2].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==id) continue;
a=(poly[id].u-poly[i].u)/(poly[id].u*poly[i].u);
b=(poly[id].v-poly[i].v)/(poly[id].v*poly[i].v);
c=(poly[id].w-poly[i].w)/(poly[id].w*poly[i].w);
///如果a=0,b=0,c<0,无解,返回0
if(dcmp(a)==0&&dcmp(b)==0&&c<esp) return 0; ///判断小于0,要<esp,dcmp(c)<0,不能A,还未知
// if(a==0&&b==0&&c<esp) return 0;
cut(p,cnt); ///用直线ax+by+c==0切割多边形
}
double area=0;
for(int i=2;i<cnt;i++) ///计算面积
area+=Cross(p[i]-p[1],p[i+1]-p[1]);
area=area/2.0;
if(dcmp(area)==0) return 0; ///面积为0,说明无解,返回0
else return 1;
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=0;i<n;i++)
scanf("%lf%lf%lf",&poly[i].u,&poly[i].v,&poly[i].w);
for(int i=0;i<n;i++)
{
if(solve(i)) puts("Yes");
else puts("No");
}
}
return 0;
}
/*
p[1].x=0.357143,p[1].y=0.035714
p[2].x=1.624650,p[2].y=1.176471
p[3].x=4.666667,p[3].y=0.466667
*/