題意:一個人在空間直角座標系的原點,即是(0,0,0), 他的射程範圍是以R爲半徑的球體,有n只蚊子,每隻蚊子都會有原始座標和三個座標方向的速度,人要儘量把多的蚊子射下來,並且開槍次數最少。
思路:假設一隻蚊子能進入這個球體,必然有一個進入時間和離開時間,我們設爲t,蚊子當前座標爲x = ax + dx * t, y = ay + dy * t, z = az + dz * t, 通過兩點距離公式可知
(x - 0)^2 + (y - 0)^2 + (z - 0)^2 <= r,把r移到不等式左邊,進行化簡,就是一條一元二次不等式,接下來就是簡單的高中求範圍問題了,特別要注意b^2 - 4*a *c>0的時候,
也會有不滿足的情況 如x1 < 0, 此時把x1 = 0, 或者x1,x2都小於0, 那麼此時無解。
求出能進入這個球體的每個蚊子的l,r區間後,那麼就變成經典的貪心問題,區間選點問題
還有我的R忘記設longlong了,訓練的時候一直wa,真是把隊友坑了
題目鏈接:http://acm.fzu.edu.cn/problem.php?pid=2144
#include <cstdio>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn =100005;
double eps = 1e-8;
struct node
{
double x, y, z;
double dx, dy, dz;
} e[maxn];
struct dis
{
double l, r;
} a[maxn];
int n, cnt;
long long r;
bool cmp(const dis &a, const dis &b)
{
if(fabs(a.r - b.r)>eps)
return a.r < b.r;
return a.l > b.l;
}
void cal(node d, double &a, double &b, double &c)
{
a = d.dx * d.dx + d.dy * d.dy + d.dz * d.dz;
b = 2 * (d.x * d.dx + d.y * d.dy + d.z * d.dz);
c = d.x * d.x + d.y * d.y + d.z * d.z - r * r;
//printf("%I64d\n", c);
}
double cal_del(double a, double b, double c)
{
return b * b - 4 * a * c;
}
void solve(node d)
{
double a1, b, c;
cal(d, a1, b, c);
double del = cal_del(a1, b, c);
if(del < 0)
return ;
else if(del > 0)
{
double x1 = (-1.0 * b - sqrt(del * 1.0)) / (2.0 * a1);
double x2 = (-1.0 * b + sqrt(del * 1.0)) / (2.0 * a1);
if(x2 < 0) return ;
if(x1 < 0)
a[cnt].l = 0.0;
else
a[cnt].l = x1;
a[cnt++].r = x2;
}
else
{
double x = -1.0 * b / (2.0 * a1);
if(x < 0)
return ;
a[cnt].l = x, a[cnt++].r = x;
}
}
int main()
{
int t;
int cas = 1;
scanf("%d", &t);
while(t--)
{
scanf("%d%d",&n, &r);
long long q, w, e1,r1,t, y;
for(int i = 0; i < n; i++)
{
scanf("%I64d%I64d%I64d%I64d%I64d%I64d", &q, &w, &e1, &r1, &t, &y);
e[i].x = q * 1.0, e[i].y = w * 1.0, e[i].z = e1 *1.0, e[i].dx = r1 *1.0, e[i].dy = t *1.0, e[i].dz = y *1.0;
}
cnt = 0;
for(int i = 0; i < n; i++)
{
solve(e[i]);
}
sort(a, a + cnt, cmp);
int ans=1;
double temp = a[0].r;
for(int i=1; i<cnt; i++)
{
if(temp<a[i].l)
{
ans++;
temp=a[i].r;
}
}
if(cnt == 0)
printf("Case %d: 0 0\n", cas++);
else
printf("Case %d: %d %d\n", cas++, cnt, ans);
}
return 0;
}