FZU 2144(几何+贪心区间覆盖)

题意:三维空间给出n个蚊子的初始位置(ax,ay,az)和移动趋势(dx,dy,dz),那么每个蚊子坐标随时间变化的函数就是(ax+dx*t, ay+dy*t, ax+dz*t)。每次射杀一枪,可以把距离原点距离len之内的蚊子全部杀死。问最多能射杀几只蚊子,这时至少要射杀几次?


解法:先求出每只蚊子在射程之内的时间区间,即(ax+dx*t, ay+dy*t, ax+dz*t)^2<=len:解一元二次方程。如果两个解都小于0,则说明此蚊子不会被杀死。算出所有能被射杀的蚊子的时间区间以后就变成了另一个经典的区间覆盖问题。将能够被杀死的蚊子的时间区间按右边界排序,然后第一个右区间可以照顾到的左区间的蚊子都可以在这时的一枪被射杀,依次往后迭代,复杂度O(n)。所以总体复杂度在于排序的nlogn上。

代码:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <iostream>  
  2. #include <stdio.h>  
  3. #include <cstring>  
  4. #include <algorithm>  
  5. #include <cmath>  
  6. using namespace std;  
  7. struct point  
  8. {  
  9.     double ax,ay,az,dx,dy,dz;  
  10. } points[100010];  
  11. struct time  
  12. {  
  13.     double x,y;  
  14.   
  15. } times[100010];  
  16.  inline bool operator<(time a,time b)  
  17.     {  
  18.         return a.y<b.y;  
  19.     }  
  20. int n;  
  21. int m=0;  
  22. double len;  
  23. void make(int i)  
  24. {  
  25.     point p=points[i];  
  26.     double a=p.dx*p.dx+p.dy*p.dy+p.dz*p.dz;  
  27.     double b=2*(p.ax*p.dx+p.ay*p.dy+p.az*p.dz);  
  28.     double c=p.ax*p.ax+p.ay*p.ay+p.az*p.az-len*len;  
  29.     if(b*b-4*a*c<0)  
  30.         return ;  
  31.     double tool=b*b-4.0*a*c;  
  32.     double ans1=(-b-sqrt(tool))/(2.0*a);  
  33.     double ans2=(-b+sqrt(tool))/(2.0*a);  
  34.     if(ans1<0&&ans2<0) return ;  
  35.     if(ans1<0)ans1=0;  
  36.     times[m].x=ans1,times[m++].y=ans2;  
  37. }  
  38. int main()  
  39. {  
  40.     int t;scanf("%d",&t);int an=0;  
  41.     while(t--)  
  42.     {  
  43.         an++;  
  44.         m=0;  
  45.         scanf("%d%lf",&n,&len);  
  46.         for(int i=0;i<n;i++){  
  47.             scanf("%lf%lf%lf",&points[i].ax,&points[i].ay,&points[i].az);  
  48.             scanf("%lf%lf%lf",&points[i].dx,&points[i].dy,&points[i].dz);  
  49.             make(i);  
  50.             }  
  51.         stable_sort(times,times+m);  
  52.         int ans=0;  
  53.         for(int i=0;i<m;i++)  
  54.         {  
  55.             int p=i+1;  
  56.             while(p<m&×[p].x<=times[i].y)  
  57.                 p++;  
  58.             ans++;  
  59.             i=p-1;  
  60.         }  
  61.         printf("Case %d: %d %d\n",an,m,ans);  
  62.     }  
  63.     return 0;  
  64. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值