fzu 2144 Shooting Game 区间覆盖贪心

来源:互联网 发布:单片机软件工程师具备 编辑:程序博客网 时间:2024/05/18 16:38

题意:一个人在空间直角坐标系的原点,即是(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;}




0 0