您的位置:首页 > 其它

FZU 2144 几何+贪心

2014-07-21 10:26 316 查看
Problem 2144 Shooting Game

Accept: 199 Submit: 1044

Time Limit: 1000 mSec Memory Limit : 32768 KB



Problem Description

Fat brother and Maze are playing a kind of special (hentai) game in the playground. (Maybe it’s the OOXX game which decrypted in the last problem, who knows.) But as they don’t like using repellent while playing this kind of special (hentai) game, they really
suffer a lot from the mosquito. So they decide to use antiaircraft gun to shoot the mosquito. You can assume that the playground is a kind of three-dimensional space and there are N mosquitoes in the playground. Each of them is a kind of point in the space
which is doing the uniform linear motion. (匀速直线运动) Fat brother is standing at (0, 0, 0) and once he shoot, the mosquito who’s distance from Fat brother is no large than R will be shot down. You can assume that the area which Fat brother shoot is a kind of
a sphere with radio R and the mosquito inside this sphere will be shot down. As Fat brother hate these mosquito very much, he wants to shoot as much mosquito as he can. But as we all know, it’s tired for a man to shoot even if he is really enjoying this. So
in addition to that, Fat brother wants to shoot as less time as he can.

You can (have to) assume that Fat brother is strong enough and he don’t need to rest after shooting which means that can shoot at ANY TIME.



Input

The first line of the date is an integer T, which is the number of the text cases.

Then T cases follow, each case starts with two integers N and R which describe above.

Then N lines follow, the ith line contains six integers ax, ay, az, dx, dy, dz. It means that at time 0, the ith mosquito is at (ax, ay, az) and it’s moving direction is (dx, dy, dz) which means that after time t this mosquito will be at (ax+dx*t, ay+dy*t,
ax+dz*t). You can assume that dx*dx + dy*dy+ dz*dz > 0.

1 <= T <= 50, 1 <= N <= 100000, 1 <= R <= 1000000

-1000000 <= ax, ay, az <= 1000000

-100 <= dx, dy, dz <= 100

The range of each coordinate is [-10086, 10086]



Output

For each case, output the case number first, then output two numbers A and B.

A is the number of mosquito Fat brother can shoot down.

B is the number of times Fat brother need to shoot.



Sample Input

62 12 0 0 -1 0 0-2 0 0 1 0 02 14 0 0 -1 0 0-2 0 0 1 0 02 14 0 0 -1 0 01 0 0 1 0 02 11 1 1 1 1 1-1 -1 -1 -1 -1 -11 10 0 0 1 0 03 1-1 0 0 1 0 0-2 0 0 1 0 04 0 0 -1 0 0



Sample Output

Case 1: 2 1Case 2: 2 1Case 3: 2 2Case 4: 0 0Case 5: 1 1Case 6: 3 2

题意:空间内有若干只蚊子,蚊子会朝着一个方向不停地飞,一个人站在原点拿着一把枪,他可以在任何时间开枪,每次他开枪,周围半径为r的球以内的蚊子会全部被射死,问他最多能射死多少蚊子,以及射死这么多蚊子所需用的最短时间。

思路:先求出每只蚊子飞行轨迹的直线方程(参数方程,参数为t): (X-X0)/Vx = (Y-Y0)/Vy = (Z-Z0)/Vz = t,t带到球面坐标方程x*x+y*y+z*z = r*r,如果无解,说明蚊子飞行时永远不会进入球内,否则会有两个解,所以排除这种情况。如果有解,设其中小的为t1,大的为t2,如果t2<0,说明蚊子要倒着飞才能飞进球内,排除这种情况。最后对每只能够飞进球内的蚊子按照最晚飞进球内的时间排序。然后从前往后遍历蚊子,每次选取当前蚊子的t2作为开枪的时间,往后的蚊子如果其t1值小于上一次开枪的时间,就跳过这只蚊子(说明它在上一次开枪时就被打死)。最后就能得到结果。

吐槽:一开始调试看数据的时候SBB的看错,以为是没有初始化,想都没想就加上两条初始化,导致后来死命的TLE

。还有更奇葩的是一开始脑子有YY只有整数时间能开枪,于是就对解出来的t1,t2取整,一时脑残两个都向上取整,结果交上去竟然过了!!估计是数据有点弱。

代码:

#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <cstring>

#define MAXN 100100
#define INF 2100000000
#define esp 1e-6
using namespace std;

double n, r;

struct point
{
public:
double t1, t2;
};

point p[MAXN];
int cnt;

int cmp(const void* a, const void* b)
{
point* p1 = (point*)a;
point* p2 = (point*)b;
return (p1->t2) - (p2->t2);
}
int main()
{
//freopen("C:/Users/Admin/Desktop/in.txt", "r", stdin);
int t;
scanf("%d", &t);
int cas = 0;
while(t--)
{
scanf("%lf%lf", &n, &r);

cnt = 0;
int maxsum = 0;

for(int i = 0; i < n; i++)
{
double x, y, z, vx, vy, vz;
scanf("%lf%lf%lf%lf%lf%lf", &x, &y, &z, &vx, &vy, &vz);

double a = (vx*vx + vy*vy + vz*vz);
double b = 2*(x*vx + y*vy + z*vz);
double c = x*x + y*y + z*z - r*r;
if(b*b-4*a*c >= 0)
{
double tt1 = (-b-sqrt(b*b-4*a*c))/(2*a);
double tt2 = (-b+sqrt(b*b-4*a*c))/(2*a);

if(tt2+esp > 0)
{
p[cnt].t1 = tt1;
p[cnt].t2 = tt2;
cnt++;
maxsum++;
}
}
}
if(cnt == 0)
{
printf("Case %d: %d %d\n", ++cas, 0, 0);
continue;
}
qsort(p, cnt, sizeof(p[0]), cmp);

int  ans = 0;
double curt;

for(int i = 0; i < cnt; i++)
{
curt = p[i].t2;
ans++;
while(i+1 < cnt && p[i+1].t1 <= curt)
{
i++;
}

}
printf("Case %d: %d %d\n", ++cas, maxsum, ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: