首页 > 代码库 > FZU 2144(几何+贪心区间覆盖)

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 plaincopy在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. }