題意:三維空間給出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上。
代碼:
- #include <iostream>
- #include <stdio.h>
- #include <cstring>
- #include <algorithm>
- #include <cmath>
- using namespace std;
- struct point
- {
- double ax,ay,az,dx,dy,dz;
- } points[100010];
- struct time
- {
- double x,y;
- } times[100010];
- inline bool operator<(time a,time b)
- {
- return a.y<b.y;
- }
- int n;
- int m=0;
- double len;
- void make(int i)
- {
- point p=points[i];
- double a=p.dx*p.dx+p.dy*p.dy+p.dz*p.dz;
- double b=2*(p.ax*p.dx+p.ay*p.dy+p.az*p.dz);
- double c=p.ax*p.ax+p.ay*p.ay+p.az*p.az-len*len;
- if(b*b-4*a*c<0)
- return ;
- double tool=b*b-4.0*a*c;
- double ans1=(-b-sqrt(tool))/(2.0*a);
- double ans2=(-b+sqrt(tool))/(2.0*a);
- if(ans1<0&&ans2<0) return ;
- if(ans1<0)ans1=0;
- times[m].x=ans1,times[m++].y=ans2;
- }
- int main()
- {
- int t;scanf("%d",&t);int an=0;
- while(t--)
- {
- an++;
- m=0;
- scanf("%d%lf",&n,&len);
- for(int i=0;i<n;i++){
- scanf("%lf%lf%lf",&points[i].ax,&points[i].ay,&points[i].az);
- scanf("%lf%lf%lf",&points[i].dx,&points[i].dy,&points[i].dz);
- make(i);
- }
- stable_sort(times,times+m);
- int ans=0;
- for(int i=0;i<m;i++)
- {
- int p=i+1;
- while(p<m&×[p].x<=times[i].y)
- p++;
- ans++;
- i=p-1;
- }
- printf("Case %d: %d %d\n",an,m,ans);
- }
- return 0;
- }