HDU4024 Dwarven Sniper’s hunting

来源:互联网 发布:百度云管家网络异常1 编辑:程序博客网 时间:2024/06/04 01:37

题意:Dw要在充分展现自己枪法的前提下用最少的时间杀死Ly,Dw的枪法的半径为L(在目标点离他距离D<=L他才能射到目标点)。Ly起始坐标为(X1,Y1),且Ly一直以(Lx,Ly)的速度矢量在前进。Dw的起始坐标为(X2,Y2),Dw的速度为vD,子弹的速度为vB。问子弹飞的距离最远为多少,杀死Ly最少要多少秒?


思路:第一个问题感觉很傻逼...因为都说了要充分展现枪法所以子弹飞的最远距离肯定为L。所以子弹飞的时间也确定了为。题目中(Lx*Lx+Ly*Ly) < vD*vD < vB*vB ,意思是Ly的速度 < Dw速度 < 子弹的速度,所以一定有解。假设Dw花费了时间杀死Ly(总追击时间),那么Ly的终点为,因为子弹飞行距离为L,所以子弹的发射点一定在以终点为圆心以L为半径的圆上,共有两种情况如下图:

情况一:d(Dw到终点的距离) = L(子弹飞的距离) + S(Dw跑的距离)

情况二:d(Dw到终点的距离) = L(子弹飞的距离) - S(Dw跑的距离)


Dw必须跑到圆周上才可以进行距离为L的射击,显然最短的一条路为L + S或L - S,子弹飞的时间一定为。Dw跑的时间为,Dw跑的距离为。且Dw到终点的距离d可以用表示为。Dw要在充分展现枪法的情况下花最短时间内杀死Ly,则有如下两个关于一元二次方程,我们可以通过二分或解方程得到答案





解方程法:

#include<bits/stdc++.h>using namespace std;const double INF = 10000000005.0;int main(){double X1, Y1, X2, Y2, Lx, Ly, vD, vB, L;while(~scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf", &X1, &Y1, &X2, &Y2, &Lx, &Ly, &vD, &vB, &L)){//Ly坐标(X1,Y1)Ly速度矢量(Lx,Ly)//Dw坐标(X2,Y2)Dw速度vD,枪法半径为L //子弹速度vBif(X1 == 0 && Y1 == 0 && X2 == 0 && Y2 == 0  && Lx == 0 && Ly == 0 && vD == 0 && vB == 0 && L == 0) break; //M,N方便化简 double M = X1 - X2 + L * Lx / vB, N = Y1 - Y2 + L * Ly / vB;//化简为at^2 + bt + c = 0 double a = pow(Lx, 2) + pow(Ly, 2) - pow(vD, 2),    b1 = 2.0 * Lx * M + 2.0 * Ly * N - 2.0 * L * vD,//L+s的情况     b2 = 2.0 * Lx * M + 2.0 * Ly * N + 2.0 * L * vD,//L-s的情况        c = pow(M, 2) + pow(N, 2) - pow(L, 2);//求根公式 double t1 = (-b1 + sqrt(pow(b1, 2) - 4.0 * a * c)) / (2.0 * a),   t2 = (-b1 - sqrt(pow(b1, 2) - 4.0 * a * c)) / (2.0 * a),   t3 = (-b2 + sqrt(pow(b2, 2) - 4.0 * a * c)) / (2.0 * a),   t4 = (-b2 - sqrt(pow(b2, 2) - 4.0 * a * c)) / (2.0 * a);//除掉负数最小的那个就是答案 if(t1 < 0.0) t1 = INF;if(t2 < 0.0) t2 = INF;if(t3 < 0.0) t3 = INF;if(t4 < 0.0) t4 = INF;printf("%.3lf %.3lf\n", L, min(min(t1,t2), min(t3,t4)) + L / vB);}return 0;}

二分法:

#include<bits/stdc++.h>using namespace std;const double eps = 1e-8;//精度 double X1, Y1, X2, Y2, Lx, Ly, vD, vB, L;double distance(double x1, double y1, double x2, double y2)//两点间距离 {return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2));}double check(double t){double x = X1 + Lx * t, y = Y1 + Ly * t;//t秒后Ly所在位置 即 终点 double d = distance(X2, Y2, x, y);//Dw的起点与Ly的终点间距离 double s = (t - (L / vB)) * vD;//Dw能跑的距离 if(d <= L)//Dw在以终点为圆心以L为半径的圆里面   即L - s{if(d < L - s) return false;//跑不到L划的圆上 return true;//能跑到 } else//在圆外   即L + s{if(d > L + s) return false;//跑不到L划的圆上 return true;//能跑到 }}int main(){while(~scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf", &X1, &Y1, &X2, &Y2, &Lx, &Ly, &vD, &vB, &L)){if(X1 == 0 && Y1 == 0 && X2 == 0 && Y2 == 0  && Lx == 0 && Ly == 0 && vD == 0 && vB == 0 && L == 0) break; //二分时间t double l = 0, r = 1000000.0, m = l + (r - l) / 2.0;while(r - l > eps){if(check(m)) r = m; else l = m;m = l + (r - l) / 2.0; }printf("%.3lf %.3lf\n", L, m);}return 0;}/*-1 0 0 10 1 0 2 10 100 0 0 5 0 1 2 6 60 0 0 0 0 0 0 0 0*/