fzu 2144 Shooting Game 区间覆盖贪心

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




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章