首页 > 代码库 > 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
- #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;
- }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。