Poj 1755 Triathlon (半平面交求可行域)
2012-12-28 23:50
465 查看
题目链接:http://poj.org/problem?id=1755
题意:有n个人参加三个赛段的比赛,三段总长一定,对于第i个人其在每一个赛段的速度分别为Vi,Ui,Wi,你作为一个裁判可以随意调整三个赛段的距离(都大于0),问是否能调整使得指定的选手获胜(不能并列)。
思路:设三个赛段的长度分别为a,b,c,则对第i人;用时分别为a/Vi,b/Ui,c/Wi,总时间Ti,获得冠军等价于对于任意第j人(j!=i),有Ti<Tj,即(1/Vi-1/Vj)*a+(1/Ui-1/Uj)*b+(1/Wi-1/Wj)*c<0,对不等式化简(令X=a/c,Y=b/c,A=1/Vi-1/Vj,B=1/Ui-1/Uj,C=1/Wi-1/Wj)得:A*X+B*Y+C<0。于是问题转化为半平面求交,先初始化一个大平面,然后用不等式表示的直线去切即可。
精度设为1e-16可过,虽然我尝试了把(1/Vi-1/Vj)写成(Vj-Vi)/(Vi*Vj),但貌似精度并没有明显提高……
学长的博文对平面的形状分析的更透彻:
http://www.cnblogs.com/jianglangcaijin/archive/2012/12/27/2836095.html
题意:有n个人参加三个赛段的比赛,三段总长一定,对于第i个人其在每一个赛段的速度分别为Vi,Ui,Wi,你作为一个裁判可以随意调整三个赛段的距离(都大于0),问是否能调整使得指定的选手获胜(不能并列)。
思路:设三个赛段的长度分别为a,b,c,则对第i人;用时分别为a/Vi,b/Ui,c/Wi,总时间Ti,获得冠军等价于对于任意第j人(j!=i),有Ti<Tj,即(1/Vi-1/Vj)*a+(1/Ui-1/Uj)*b+(1/Wi-1/Wj)*c<0,对不等式化简(令X=a/c,Y=b/c,A=1/Vi-1/Vj,B=1/Ui-1/Uj,C=1/Wi-1/Wj)得:A*X+B*Y+C<0。于是问题转化为半平面求交,先初始化一个大平面,然后用不等式表示的直线去切即可。
精度设为1e-16可过,虽然我尝试了把(1/Vi-1/Vj)写成(Vj-Vi)/(Vi*Vj),但貌似精度并没有明显提高……
学长的博文对平面的形状分析的更透彻:
http://www.cnblogs.com/jianglangcaijin/archive/2012/12/27/2836095.html
#include <cstdio> #include <iostream> #include <cmath> #include <algorithm> using namespace std; const double EPS=1e-16; const int NUM=110; int DB (double x) { if (x>EPS) return 1; if (x<-EPS) return -1; return 0; } struct Set { double v,u,w; void get () { scanf("%lf%lf%lf",&v,&u,&w); } }data[NUM]; struct Point { double x,y; Point(){} Point(double _x,double _y) { x=_x; y=_y; } }p[NUM],q[NUM]; int n; double r; int cCnt,curCnt; bool flag,judge; Point intersect (Point x,Point y,double a,double b,double c) //相交 { double u = fabs(a * x.x + b * x.y + c); double v = fabs(a * y.x + b * y.y + c); return Point( (x.x * v + y.x * u) / (u + v) , (x.y * v + y.y * u) / (u + v) ); } /*半平面相交(直线切割多边形)(点标号从1开始)*/ void cut (double a,double b ,double c) { int i; curCnt = 0; for (i=1;i<=cCnt;i++) { if (DB(a*p[i].x + b*p[i].y + c) >= 0) //大于0为可行域 q[++curCnt] = p[i]; else { if (DB(a*p[i-1].x + b*p[i-1].y + c) > 0) q[++curCnt] = intersect(p[i],p[i-1],a,b,c); if (DB(a*p[i+1].x + b*p[i+1].y + c) > 0) q[++curCnt] = intersect(p[i],p[i+1],a,b,c); } } for (i=1;i<=curCnt;i++) p[i] = q[i]; p[curCnt+1] = q[1]; p[0] = p[curCnt]; cCnt = curCnt; double area=0; for (i=1;i<=curCnt;i++) area += p[i].x * p[i + 1].y - p[i + 1].x * p[i].y; area = fabs(area / 2.0); if (area < EPS) flag=false; } int main () { while (~scanf("%d",&n)) { int i,j; for (i=1;i<=n;i++) data[i].get(); for (i=1;i<=n;i++) { flag=true; judge=true; p[1] = Point(0,0); p[2] = Point(0,1000000); p[3] = Point(1000000,1000000); p[4] = Point(1000000,0); p[5] = p[1]; p[0] = p[4]; cCnt = 4; for (j=1;j<=n;j++) { if (i == j) continue; double A=(data[j].v-data[i].v)/(data[j].v*data[i].v);//1.0/data[i].v-1.0/data[j].v; double B=(data[j].u-data[i].u)/(data[j].u*data[i].u);//1.0/data[i].u-1.0/data[j].u; double C=(data[j].w-data[i].w)/(data[j].w*data[i].w);//1.0/data[i].w-1.0/data[j].w; A=-A; //我的模板要求Ax+By+C的可行域为>0,本题要求<0 B=-B; C=-C; if (A==0 && B==0 && C==0) { judge=false; break; } cut(A,B,C); } if (judge && flag) printf("Yes\n"); else printf("No\n"); } } return 0; } /* 11 10 2 6 10 2 6 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 Out No No No Yes Yes No No No Yes No Yes */
相关文章推荐
- poj 1755 Triathlon(半平面交解可行域)
- [POJ][1755][Triathlon][半平面交]
- POJ 1755 Triathlon 半平面交
- POJ 1755 Triathlon 半平面交
- POJ 1755 Triathlon 半平面交
- POJ 1755-Triathlon(半平面交-铁人三项)
- poj 1755 Triathlon 半平面交判断不等式是否有解
- POJ 1755 Triathlon(线性规划の半平面交)
- 【半平面交】 POJ 1755 Triathlon
- poj 1755 Triathlon 半平面交
- POJ 1755 Triathlon(n^2 半平面交, 两点式和参数式直线求交点)
- POJ 1755 Triathlon [半平面交 线性规划]
- POJ 1755 Triathlon(半平面交解不等式)
- BZOJ 3800 Saber VS Lancer/POJ 1755 Triathlon 半平面交
- POJ 1755 Triathlon(半平面交)
- POJ 1755 Triathlon 半平面交
- POJ 1755 Triathlon【半平面交】
- poj 1755 Triathlon (半平面交求解不等式组)
- POJ 1755 Triathlon (半平面交)
- POJ 1755 Triathlon 半平面交