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;
}




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