题意比较简单,就是给N个蚊子,主人公站在(0,0,0)这个位置上,然后N个蚊子有各自的起始点和移动方向,主人公可以在任意时间攻击,攻击的时候那些跟他距离不超过R的蚊子就算被击中,问最多能击中多少个以及最少要攻击几次。
做法就是对每个蚊子,求出它落在攻击范围内的时间段,列个关于时间t的距离不等式求解即可。
然后按照结束时间的顺序排序,贪心一下即可。
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
struct Event{
double st, ed;
bool operator < (const Event& a)const{
return ed<a.ed;
}
}ev[100000];
int t, n, i, j, m, cnt;
double r, ax, ay, az, dx, dy, dz, a, b, c, d;
inline void getnum(int& x){
char ch=getchar();
bool mk=0;
x = 0;
while(ch<48 || ch>57){
if(ch=='-') mk=1;
ch=getchar();
}
while(ch>=48 && ch<=57){
x = x*10+ch-48;
ch = getchar();
}
if(mk) x=-x;
}
inline void getnum(double& x){
int y;
getnum(y);
x = y*1.0;
}
int main(){
getnum(t);
for(int ct=1; ct<=t; ct++){
m=0;
getnum(n);
getnum(r);
while(n--){
getnum(ax); getnum(ay); getnum(az);
getnum(dx); getnum(dy); getnum(dz);
a = dx*dx+dy*dy+dz*dz;
b = 2*(ax*dx+ay*dy+az*dz);
c = ax*ax+ay*ay+az*az-r*r;
d = b*b-4*a*c;
if(d<0) continue;
ev[m].st = (b*(-1)-sqrt(d))/(a*2);
ev[m].ed = (b*(-1)+sqrt(d))/(a*2);
if(ev[m].st<0 && ev[m].ed<0) continue;//两个同时小于0表明不可能进入攻击范围
m++;
}
printf("Case %d: %d ", ct, m);
cnt=0;
sort(ev, ev+m);
for(i=0; i<m; i++){
cnt++;
a = ev[i].ed;
j=i+1;
while(j<m){
if(ev[j].st<=a && ev[j].ed>=a){
j++;
}
else break;
}
i = j-1;
}
printf("%d\n", cnt);
}
return 0;
}