1 条题解
-
0
自动搬运
来自洛谷,原作者为

ycyaw
无他,唯勤尔搬运于
2025-08-24 21:43:31,当前版本为作者最后更新于2019-06-05 15:09:37,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
没有题解,来补一篇。
观察到题目中和杀手都在动,所以考虑相对运动,以的位置作为原点,不动,只考虑杀手运动。让不动,直接杀手的位置和速度减去的即可。
考虑杀手攻击半径为,转化一下即进入以为圆心,为半径的圆,就可攻击到。
所以我们只要求出每个杀手进入该圆与离开该圆的时间点即可。最后就可以对所以时间点进行排序,然后对整条时间线进行类似于扫描线的方法统计答案。
显然就是这样一张图:

求出直线与圆的交点即可。
设杀手起点为,速度为,设在时刻恰好在交点,那么:
化简得到一个一元二次方程:
$$(vx^2+vy^2)\times t^2+(2x\times vx+2y\times vy)\times t+x^2+y^2-r^2=0 $$解出来即可。即程序里的
注意判断均为0的情况。
#include<bits/stdc++.h> #define ts cout<<"ok"<<endl #define int long long #define hh puts("") using namespace std; int n,r,top; double bx,by,bvx,bvy,eps=1e-8,L,R; struct node{ double x,y,vx,vy; }a[500005]; struct TM{ double t; int s; }b[500005]; inline int read(){ int ret=0,ff=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-') ff=-1;ch=getchar();} while(isdigit(ch)){ret=(ret<<3)+(ret<<1)+(ch^48);ch=getchar();} return ret*ff; } inline void work(double A,double B,double C){//a*t*t+b*t+c=0 if(fabs(A)<eps){ if(C<=0) L=0,R=1e9; else L=R=-1; return; } double delta=B*B-4*A*C; if(delta<0){//一元二次方程判根 L=R=-1; return; } L=(-B-sqrt(delta))/(2*A); R=(-B+sqrt(delta))/(2*A); if(L<0) L=0; if(R<0) R=-1; } inline bool cmp(TM a,TM b){ return a.t<b.t; } signed main(){ n=read(),r=read(); bx=read(),by=read(),bvx=read(),bvy=read(); for(int i=1;i<=n;i++){ a[i].x=read()-bx; a[i].y=read()-by; a[i].vx=read()-bvx; a[i].vy=read()-bvy; } for(int i=1;i<=n;i++){ double ds=a[i].x*a[i].x+a[i].y*a[i].y-r*r; work(a[i].vx*a[i].vx+a[i].vy*a[i].vy,2*a[i].x*a[i].vx+2*a[i].y*a[i].vy,ds); if(R!=-1) b[++top]=(TM){L,1},b[++top]=(TM){R,-1}; } sort(b+1,b+top+1,cmp); int sum=0,ans=0; for(int i=1;i<=top;i++){ sum+=b[i].s; ans=max(ans,sum); } printf("%lld",ans); return 0; }
- 1
信息
- ID
- 1993
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者