考试题T3
题意分析
这题一看没有什么思路
幸好我们机房的红太阳\(ghj1222\)切了这道题
首先我们考虑风跑一个来回之后人怎么样
就是跑了一个区间
也就是风跑了若干个来回之后 人跑了若干个区间
所以我们考虑求出距离最小的那个区间
距离是一个单峰函数 所以我们用三分求
然后的话 问题就是求两条有向线段之间的最小距离
这也是一个单峰函数 所以我们用三分求
我们需要处理出来风从一头走到另一头的人的走的向量
\[\frac{\overrightarrow{v}}{|\overrightarrow{v}|}\frac{v_w}{v_t}dis
\]
$dis: $风走的距离
CODE:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<string>
#include<queue>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<deque>
#include<vector>
#include<ctime>
#define ll long long
#define inf 0x7fffffff
#define N 500008
#define IL inline
#define M 1008611
#define D double
#define eps 1e-7
#define R register
using namespace std;
template<typename T>IL void read(T &_)
{
T __=0,___=1;char ____=getchar();
while(!isdigit(____)) {if(____=='-') ___=0;____=getchar();}
while(isdigit(____)) {__=(__<<1)+(__<<3)+____-'0';____=getchar();}
_=___ ? __:-__;
}
/*-------------OI使我快乐-------------*/
struct Node
{
D xx,yy;
friend Node operator +(const Node &A,const Node &B)
{return (Node){A.xx+B.xx,A.yy+B.yy};}
friend Node operator -(const Node &A,const Node &B)
{return (Node){A.xx-B.xx,A.yy-B.yy};}
friend Node operator *(const Node &A,const D &B)
{return (Node){A.xx*B,A.yy*B};}
friend Node operator /(const Node &A,const D &B)
{return (Node){A.xx/B,A.yy/B};}
}fro_x,to_x,fro_y,to_y,tmp;
D v_x,v_y,d_x,d_y;
IL D qury_dis(Node now)
{return sqrt((now.xx*now.xx)+(now.yy*now.yy));}
IL D qury_ans(const Node &sx,const Node &tx,const Node &sy,const Node &ty)
{//三分最小的距离
Node tmpx=tx-sx,tmpy=ty-sy;
D le=0,ri=1,ans=0;
while((ri-le)>eps)
{
D mid=(ri-le)/3.0+le,mmid=ri-(ri-le)/3.0;
Node cdy,wzy,zjz,ghj;
cdy=sx+tmpx*mid;wzy=sy+tmpy*mid;
zjz=sx+tmpx*mmid;ghj=sy+tmpy*mmid;
//这里要注意的是 二者的进行是等比例的
D dis_cdy=qury_dis(wzy-cdy),dis_wzy=qury_dis(ghj-zjz);
if(dis_cdy>dis_wzy) le=mid,ans=dis_wzy;
else ri=mmid,ans=dis_cdy;
}
return ans;
}
IL D work(ll now)
{
Node cdy,wzy,zjz;
cdy=fro_x+tmp*now*2;wzy=cdy+tmp;zjz=wzy+tmp;
return min(qury_ans(cdy,wzy,fro_y,to_y),qury_ans(wzy,zjz,to_y,fro_y));
}
int main()
{
freopen("chaser.in","r",stdin);
freopen("chaser.out","w",stdout);
while(scanf("%lf%lf",&fro_x.xx,&fro_x.yy)!=EOF)
{
scanf("%lf%lf%lf",&to_x.xx,&to_x.yy,&v_x);
scanf("%lf%lf%lf%lf%lf",&fro_y.xx,&fro_y.yy,&to_y.xx,&to_y.yy,&v_y);
tmp=((to_x-fro_x)/qury_dis(to_x-fro_x)*v_x/v_y*qury_dis(to_y-fro_y));
//相当于是风跑一个来回之后
//人在其方向上走的向量
// printf("now is %.2f %.2f\n",tmp.xx,tmp.yy);
scanf("%lf%lf",&d_x,&d_y);
//三分区间对应的位置
ll le=0,ri=1e13;
while(ri-le>=5)
{
//ghj1222说 整数三分卡边界比较恶心 所以设置一个误差 然后暴力求就可以了
ll mid=(ri-le)/3+le,mmid=ri-(ri-le)/3;
D resa=work(mid),resb=work(mmid);
if(resa>resb) le=mid;
else ri=mmid;
}
D ans=1e18;
for(R ll i=le;i<=ri;++i)
ans=min(ans,work(i));
if(ans<d_x) puts("Dangerous");
else if(ans>=d_x&&ans<=d_y) puts("Perfect");
else puts("Miss");
}
fclose(stdin);
fclose(stdout);
return 0;
}