HDU 4024 Dwarven Sniper’s hunting【水二分】
这。。。。。这题难道自带“错误题意引导”???为啥我就算读对了题意,想对了做法,结果敲的时候又按照错误的想法敲了呢?伤不起。。其实04题才是本场最水题,但是- -题意太坑爹了。唉。
题意:
二维平面追击。
被追击的人有起始坐标,有一个速度矢量,从开始就一直在走。
追击者有起始坐标,有运动速率,射出的子弹也有一个速率。子弹有一个有效射击半径。
就问,在子弹飞行距离最远的情况下,让总追击时间(被追击者被击中前的运动时间)最短,最远距离是多少,最短时间是多少。(一直搞反了题意。妹的。)
条件保证,1e9的时间内一定有解,被追者速率<追者速率<子弹速率。
第二个条件保证了,时间短的时候打不中的话,将时间拉长就一定能打中。
做法:
由于一定有解,为了让飞行距离最长,那么就让它等于射击半径。
果断二分总时间。
得出被追者当前坐标,算出与追击者起始坐标的距离。以射击半径画圆,判断追击者是在圆内还是圆外。并算出小圆半径(即去除子弹时间的剩余时间乘以追击者的运动速率)。判断两圆状态,相离或相切则l = mid,相交则r=mid。(前者表示打不着还需要继续跑,后者表示打到了但不是最优所以要缩短)。
二分中间的某些状态大概可以表示追击者跑到某个地方停了下来,然后等被追击者跑到指定位置再开始秀枪法;但鉴于最优解一定不需要让追击者有等待时间,所以最后的最优状态一定是相切的。
话说因为不小心用到了除法,所以eps开到1e-6会被卡精度,所以没办法只能1e-8了。。第一次写的时候开到1e-6竟然连样例都有精度差,这。。。
唉,被题意坑啊,自己脑子笨,想不清楚二分啊,我弱爆了。
附代码:
#include
<
iostream
>
#include < cstdio >
#include < cstring >
#include < cmath >
using namespace std;
const double eps = 1e - 6 ;
const double inf = 1e9;
int comp( double x)
{
if (fabs(x) < eps)
return 0 ;
else if (x < - eps)
return - 1 ;
else
return 1 ;
}
struct point
{
double x,y;
point(){}
point( double a, double b):x(a),y(b){}
point operator - ( const point p)
{
return point(x - p.x,y - p.y);
}
point operator * ( const double a)
{
return point(x * a,y * a);
}
point operator + ( const point p)
{
return point(x + p.x,y + p.y);
}
double norm()
{
return sqrt(x * x + y * y);
}
}p1,p2,L;
double vd,vb,limit;
int main()
{
while (scanf( " %lf %lf %lf %lf %lf %lf %lf %lf %lf " , & p1.x, & p1.y, & p2.x, & p2.y, & L.x, & L.y, & vd, & vb, & limit) == 9 )
{
if ( ! comp(p1.x) && ! comp(p1.y) && ! comp(p2.x) && ! comp(p2.y) && ! comp(L.x) && ! comp(L.y) && ! comp(vd) && ! comp(vb) && ! comp(limit))
break ;
double t2 = limit / vb;
double l = 0.0 ,r = inf,mid;
while (comp(l - r) < 0 )
{
mid = (l + r) / 2.0 ;
point now = p1 + L * mid;
if (comp(t2 - mid) > 0 )
{
l = mid;
continue ;
}
double d = (now - p2).norm();
double most = (mid - t2) * vd;
if (comp(d - limit) <= 0 )
{
if (comp(d + most - limit) < 0 )
l = mid;
else
r = mid;
}
else
{
if (comp(most + limit - d) < 0 )
l = mid;
else
r = mid;
}
}
printf( " %.3lf %.3lf\n " ,limit,mid);
}
}
#include < cstdio >
#include < cstring >
#include < cmath >
using namespace std;
const double eps = 1e - 6 ;
const double inf = 1e9;
int comp( double x)
{
if (fabs(x) < eps)
return 0 ;
else if (x < - eps)
return - 1 ;
else
return 1 ;
}
struct point
{
double x,y;
point(){}
point( double a, double b):x(a),y(b){}
point operator - ( const point p)
{
return point(x - p.x,y - p.y);
}
point operator * ( const double a)
{
return point(x * a,y * a);
}
point operator + ( const point p)
{
return point(x + p.x,y + p.y);
}
double norm()
{
return sqrt(x * x + y * y);
}
}p1,p2,L;
double vd,vb,limit;
int main()
{
while (scanf( " %lf %lf %lf %lf %lf %lf %lf %lf %lf " , & p1.x, & p1.y, & p2.x, & p2.y, & L.x, & L.y, & vd, & vb, & limit) == 9 )
{
if ( ! comp(p1.x) && ! comp(p1.y) && ! comp(p2.x) && ! comp(p2.y) && ! comp(L.x) && ! comp(L.y) && ! comp(vd) && ! comp(vb) && ! comp(limit))
break ;
double t2 = limit / vb;
double l = 0.0 ,r = inf,mid;
while (comp(l - r) < 0 )
{
mid = (l + r) / 2.0 ;
point now = p1 + L * mid;
if (comp(t2 - mid) > 0 )
{
l = mid;
continue ;
}
double d = (now - p2).norm();
double most = (mid - t2) * vd;
if (comp(d - limit) <= 0 )
{
if (comp(d + most - limit) < 0 )
l = mid;
else
r = mid;
}
else
{
if (comp(most + limit - d) < 0 )
l = mid;
else
r = mid;
}
}
printf( " %.3lf %.3lf\n " ,limit,mid);
}
}
å