POJ 1755 Triathlon

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

题意:铁人三项,每个人有自己在每一段的速度,求有没有一种3条路线长度都不为0的设计使得某个人能严格获胜?

我们枚举每个人获胜,得到不等式组:s1/v1+s2/v2+s3/v3<s1/v1‘+s2/v2‘+s3/v3‘ 是三维半平面交?接着看

我们令两边同时除以s3得到

(s1/s3)*(1/v1)+(s2/s3)*(1/v2)+(1/v3)<(s1/s3)*(1/v1‘)+(s2/s3)*(1/v2‘)+(1/v3‘)

这样s1/s3和s2/s3就变成了唯二的变量了,这样不等式组就变成了二元一次不等式组了,用半平面交就可以解决了。

注意有些地方:

eps要设置到1e-16

如果一个人有2个速度和另一个人相等,直接特判掉第三个,不建直线。

#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
const double eps=1e-16;
const double inf=99999999;
struct Point{
 double x,y;
 Point(){}
 Point(double x0,double y0):x(x0),y(y0){}
}p[200005];
struct Line{
 Point s,e;
 double slop;
 Line(){}
 Line(Point s0,Point e0):s(s0),e(e0){}
}l[200005],c[200005];
int tot,n,v1[200005],v2[200005],v3[200005],num[200005];
int sgn(double x){
 if (x>eps) return 1;
 if (x<-eps) return -1;
 return 0;
}
int read(){
 int t=0,f=1;char ch=getchar();
 while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘) f=-1;ch=getchar();}
 while (‘0‘<=ch&&ch<=‘9‘){t=t*10+ch-‘0‘;ch=getchar();}
 return t*f;
}
double operator *(Point p1,Point p2){
 return p1.x*p2.y-p1.y*p2.x;
}
Point operator -(Point p1,Point p2){
 return Point(p1.x-p2.x,p1.y-p2.y);
}
bool pd(int id){
 for (int i=1;i<=n;i++)
  if (i!=id)
 {
  int cnt=0,ans1=0,ans2=0;
  if (v1[i]==v1[id]) cnt++;
  else ans1=v1[id],ans2=v1[i];
  if (v2[i]==v2[id]) cnt++;
  else ans1=v2[id],ans2=v2[i];
  if (v3[i]==v3[id]) cnt++;
  else ans1=v3[id],ans2=v3[i];
  if (cnt==3) return 0;
  else if (cnt==2){
   if (ans1<=ans2) return 0;
  }
  num[i]=cnt;
 }
 return 1;
}
void build(int id){
    tot=0;
    l[++tot].s=Point(0,inf);l[tot].e=Point(0,0);
    l[++tot].s=Point(0,0);l[tot].e=Point(inf,0);
    l[++tot].s=Point(inf,0);l[tot].e=Point(0,inf);
    for (int i=1;i<=n;i++)
     if (i!=id){
     if (num[i]==2) continue;
     tot++;
     double A=((double)v1[i]-v1[id])/((double)v1[id]*v1[i]);
     double B=((double)v2[i]-v2[id])/((double)v2[id]*v2[i]);
     double C=((double)v3[i]-v3[id])/((double)v3[id]*v3[i]);
     int a=sgn(A),b=sgn(B),c=sgn(C);
     if (a==0){
      l[tot].s.x=-1;l[tot].s.y=(-C)/B;
      l[tot].e.x=1;l[tot].e.y=(-C)/B;
      if (b>0) std::swap(l[tot].s,l[tot].e);
     }else if (b==0){
      l[tot].s=Point((-C)/A,-1);
      l[tot].e=Point((-C)/A,1);
      if (a<0) std::swap(l[tot].s,l[tot].e);
     }else{
      l[tot].s=Point(-1,-((-1)*A+C)/B);
      l[tot].e=Point(1,-(A+C)/B);
      if (b>0) std::swap(l[tot].s,l[tot].e);
     }
 }
 for (int i=1;i<=tot;i++)
  l[i].slop=atan2(l[i].e.y-l[i].s.y,l[i].e.x-l[i].s.x);
}
Point inter(Line p1,Line p2){
 double k1=(p2.e-p1.s)*(p1.e-p1.s);
 double k2=(p1.e-p1.s)*(p2.s-p1.s);
 double t=(k2)/(k1+k2);
 double x=p2.s.x+(p2.e.x-p2.s.x)*t;
 double y=p2.s.y+(p2.e.y-p2.s.y)*t;
 return Point(x,y);
}
bool jud(Line p1,Line p2,Line p3){
 Point p=inter(p1,p2);
 return (p-p3.s)*(p3.e-p3.s)>=eps;
}
bool cmp(Line p1,Line p2){
 if (fabs(p1.slop-p2.slop)<=eps) return (p1.e-p1.s)*(p2.e-p1.s)<=0;
 else return p1.slop<p2.slop;
}
bool phi(){
   int cnt=1;
   std::sort(l+1,l+1+tot,cmp);
   for (int i=2;i<=tot;i++)
    if (fabs(l[i].slop-l[i-1].slop)>eps) l[++cnt]=l[i];
   int L=1,R=2;c[1]=l[1];c[2]=l[2];
   for (int i=3;i<=cnt;i++){
    while (L<R&&jud(c[R],c[R-1],l[i])) R--;
    while (L<R&&jud(c[L],c[L+1],l[i])) L++;
    c[++R]=l[i];
   }
   while (L<R&&jud(c[R],c[R-1],c[L])) R--;
   while (L<R&&jud(c[L],c[L+1],c[R])) L++;
   if (R-L+1<3) return 0;
   c[R+1]=c[L];
   cnt=0;
   for (int i=L;i<=R;i++)
    p[++cnt]=inter(c[i],c[i+1]);
   p[cnt+1]=p[1];
   double res=0;
   for (int i=1;i<=cnt;i++)
    res+=p[i]*p[i+1];
   res/=2.0;
   res=fabs(res);
   if (res<=eps) return 0;
   else return 1;
}
bool work(int id){
   build(id);
   if (phi()) return 1;
   else return 0;
}
int main(){
   n=read();
   for (int i=1;i<=n;i++){
    v1[i]=read(),v2[i]=read(),v3[i]=read();
   }
   for (int i=1;i<=n;i++){
    if (pd(i)&&work(i)) puts("Yes");
    else puts("No");
   }
   return 0;
}
时间: 2024-10-17 07:55:00

POJ 1755 Triathlon的相关文章

poj 1755 Triathlon 半平面交求不等式的 是否为空集-------构造有向直线

题目来源: http://poj.org/problem?id=1755 分析: 设比赛总长度为 1, 其中游泳长度为x, 自行车长度为y, 赛跑长度为 1 - x - y, 则选手 i 打败 选手j (不能并列) 的条件是 x / v[i] + y / u[i] + (1 - x - y) / w[i]  <  x / v[j] + y / u[j] + (1 - x - y) / w[j] 整理为 a*x + b * y + c > 0 (直线向量为 (b , -a))   ,  为逆时针

BZOJ 3800 Saber VS Lancer/POJ 1755 Triathlon 半平面交

题目大意:有n个人进行铁人三项比赛,对于这三种运动,每个人都有一个固定的速度,但是每种运动的长度是多少并不知道.现在问裁判可不可以通过调整这三项运动的长度来使某一个人赢得比赛. 思路:考虑现在我们想让一个人赢的时候,这个人的三个速度分别为v1,v2,v3,想让所有人都输给他,设某一个人的三个速度是v1',v2',v3'.设三项的比赛的长度为l1,l2,l3.那么不难得到如下方程:l1 / v1 + l2 / v2 + l3 / v3 < l1 / v1' + l2 / v2' + l3 / v3

POJ 1755

列出不等式后,把同时除Z把它去掉. 注意了,这里应该 是把直线变两点表示的向量更为简单,我开始就直接用直线写,后来,唉,写不下去了.. #include <iostream> #include <algorithm> #include <cstdio> #include <cmath> using namespace std; const int MAX=110; const double eps=1e-10; const double inf=1e10;

[转] POJ几何分类

转自:http://blog.csdn.net/tyger/article/details/4480029 计算几何题的特点与做题要领:1.大部分不会很难,少部分题目思路很巧妙2.做计算几何题目,模板很重要,模板必须高度可靠.3.要注意代码的组织,因为计算几何的题目很容易上两百行代码,里面大部分是模板.如果代码一片混乱,那么会严重影响做题正确率.4.注意精度控制.5.能用整数的地方尽量用整数,要想到扩大数据的方法(扩大一倍,或扩大sqrt2).因为整数不用考虑浮点误差,而且运算比浮点快. 一.点

【转】计算几何题目推荐

打算转下来好好做计算几何了. 原文地址:http://blog.sina.com.cn/s/blog_49c5866c0100f3om.html 其实也谈不上推荐,只是自己做过的题目而已,甚至有的题目尚未AC,让在挣扎中.之所以推荐计算几何题,是因为,本人感觉ACM各种算法中计算几何算是比较实际的算法,在很多领域有着重要的用途计算几何题的特点与做题要领:1.大部分不会很难,少部分题目思路很巧妙2.做计算几何题目,模板很重要,模板必须高度可靠.3.要注意代码的组织,因为计算几何的题目很容易上两百行

【转】[专题学习][计算几何]

原文地址:http://www.cnblogs.com/ch3656468/archive/2011/03/02/1969303.html 基本的叉积.点积和凸包等东西就不多说什么了,网上一搜一大堆,切一些题目基本熟悉了就差不多了. 一些基本的题目可以自己搜索,比如这个blog:http://blog.sina.com.cn/s/blog_49c5866c0100f3om.html 接下来,研究了半平面交,思想方法看07年朱泽园的国家队论文,模板代码参考自我校大牛韬哥: http://www.o

计算几何学习5

今天算是把半平面交的nlogn版本搞出来了 也做了一些半平面交的经典题 最重要的是感受到了 计算几何的精度的深深的恶意 nlogn的做法 和凸包类似 维护一个直线的双端队列 极角排序后每次加入一条直线都从队首队尾弹出无效直线 在加入时和队尾直线产生交点 最后队首队尾产生交点 中间还有当队尾两直线向量共线时的问题需要处理一下 总感觉 n^2的做法虽然慢 但是精度似乎比nlogn的要靠谱 计算几何很多特殊情况的处理让人很蛋疼 poj 3335 模板 试了下 nlogn 和 n ^ 2板子 其他比较简

优质题表(机密版)

转载请注明出处:http://www.cnblogs.com/dashuzhilin/p/4556803.html 思维题: poj 1528 poj 1597 poj 2538 poj 2608 poj 2612 poj 2361 poj 2339 poj 2664 uva 10894 uva 10921   uva 10922   uva 10929 uva 10931   uva 10800   uva 10878 uva 10976   uva 10323   uva 201 poj 2

【BZOJ】【2765】【JLOI2010】铁人双项比赛

计算几何/半平面交 本来我是想去写POJ 1755的,然后想起了这道跟它很像的题,但应该是弱化版,所以就先写了这个…… 我们可以发现每个人的总用时,与k是呈一次函数关系的:$time_i=\frac{k}{Vrun_i}+\frac{S-k}{Vride_i}$ 然而我们要找的是某个k,使得$min(time_n-time_i)$最大 那么就是一个线性规划问题了……这个也可以用半平面交来做……(蒟蒻并不会单纯形) 下面的部分为了偷懒简洁我就用$a_i$和$b_i$来代替两种速度…… 我一开始想的