POJ 2177 Ghost Busters(三维几何)
Description
The famous Ghost Busters team has decided to upgrade their Ectomobile (aka Ecto-1) with a powerful proton gun and an advanced targeting system. Egon has designed and built all the hardware which consists of ectoplasmic scanner and a proton gun that has two degrees of freedom and can automatically rotate and fire in a 90 degrees trihedral angle. You have been hired to write a prototype for the targeting software.
Ghosts are detected by ectoplasmic scanner and are represented as floating spheres. The coordinates of their centers and radii are delivered from the ectoplasmic scanner to the targeting software. The coordinate system is aligned is such a way, that the proton gun fires from the point (0, 0, 0) anywhere into X ≥ 0, Y ≥ 0, Z ≥ 0 trihedral angle. The gun fires a proton ray in a straight line and is so powerful, that even a touch of its ray is enough to kill a ghost. The ray of the proton gun is able to kill a virtually unlimited number of ghosts on its way.
For the first prototype for the targeting software, you are asked to write a program that determines the maximal number of ghosts that can be killed with a single shot of the proton gun.
Input
Output
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
using namespace std;
typedef long long LL; const double EPS = 1e-;
const double INF = 1e50;
const double PI = acos(-1.0); inline int sgn(double x) {
return (x > EPS) - (x < -EPS);
} inline double zero(double x) {
if(sgn(x) == ) return ;
else return x;
} inline double sqr(double x) {
return x * x;
} struct Point3D {
double x, y, z;
Point3D() {}
Point3D(double x, double y, double z): x(x), y(y), z(z) {}
void read() {
scanf("%lf%lf%lf", &x, &y, &z);
}
double operator * (const Point3D &rhs) const {
return x * rhs.x + y * rhs.y + z * rhs.z;
}
Point3D operator + (const Point3D &rhs) const {
return Point3D(x + rhs.x, y + rhs.y, z + rhs.z);
}
Point3D operator - (const Point3D &rhs) const {
return Point3D(x - rhs.x, y - rhs.y, z - rhs.z);
}
Point3D operator * (double rhs) const {
return Point3D(x * rhs, y * rhs, z * rhs);
}
Point3D operator / (double rhs) const {
return Point3D(x / rhs, y / rhs, z / rhs);
}
bool operator == (const Point3D &rhs) const {
return sgn(x - rhs.x) == && sgn(y - rhs.y) == && sgn(z - rhs.z) == ;
}
double length() const {
return sqrt(x * x + y * y + z * z);
}
Point3D unit() const {
return *this / length();
}
}; struct Line3D {
Point3D st, ed;
Line3D() {}
Line3D(Point3D st, Point3D ed): st(st), ed(ed) {}
}; struct Plane3D {
Point3D a, b, c;
Plane3D() {}
Plane3D(Point3D a, Point3D b, Point3D c): a(a), b(b), c(c) {}
void read() {
a.read(), b.read(), c.read();
}
}; struct Circle3D {
Point3D c;
double r;
Circle3D() {}
Circle3D(Point3D c, double r): c(c), r(r) {}
void read() {
c.read();
scanf("%lf", &r);
}
}; double dist(const Point3D &a, const Point3D &b) {
return (a - b).length();
}
//叉积
Point3D cross(const Point3D &u, const Point3D &v) {
Point3D ret;
ret.x = u.y * v.z - u.z * v.y;
ret.y = u.z * v.x - u.x * v.z;
ret.z = u.x * v.y - u.y * v.x;
return ret;
}
//点到直线距离
double point_to_line(const Point3D &p, const Line3D &l) {
return cross(p - l.st, l.ed - l.st).length() / dist(l.ed, l.st);
}
//求两直线间的距离
double line_to_line(const Line3D u, const Line3D v) {
Point3D n = cross(u.ed - u.st, v.ed - v.st);
return fabs((u.st - v.st) * n) / n.length();
}
//取平面法向量
Point3D vector_of_plane(const Plane3D &s) {
return cross(s.a - s.b, s.b - s.c);
}
//判断两直线是否平行
bool isParallel(const Line3D &u, const Line3D &v) {
return sgn(cross(u.ed - u.st, v.ed - v.st).length()) <= ;
}
//判断直线是否与球相交
bool isIntersect(const Line3D &l, const Circle3D &cir) {
return sgn(point_to_line(cir.c, l) - cir.r) <= ;
}
//直线与平面的交点
Point3D intersect(const Line3D &l, const Plane3D &s) {
Point3D ret = vector_of_plane(s);
double t = (ret * (s.a - l.st)) / (ret * (l.ed - l.st));
return l.st + (l.ed - l.st) * t;
}
//在原点上看,两个球的交点
int intersect(const Circle3D &u, const Circle3D &v, Point3D &p1, Point3D &p2) {
double d = dist(u.c, v.c);
if(u.c == v.c || sgn(d - u.r - v.r) > || sgn(fabs(u.r - v.r) - d) > ) return ;
double t = (sqr(d) + sqr(u.r) - sqr(v.r)) / ( * d);
Point3D mid = u.c + (v.c - u.c).unit() * t;
Point3D vec = cross(mid, v.c - u.c).unit() * sqrt(zero(sqr(u.r) - sqr(t)));
p1 = mid + vec;
p2 = mid - vec;
return + sgn(vec.length());
} const int MAXN = ; Circle3D cir[MAXN];
Point3D p[MAXN * MAXN], ansVec;
int maxAns, pcnt;
int n; int count(const Point3D &vec) {
int ret = ;
for(int i = ; i < n; ++i)
ret += (sgn(point_to_line(cir[i].c, Line3D(Point3D(, , ), vec)) - cir[i].r) <= );
return ret;
} void output(const Point3D &vec) {
bool flag = false;
for(int i = ; i < n; ++i) {
if(sgn(point_to_line(cir[i].c, Line3D(Point3D(, , ), vec)) - cir[i].r) <= ) {
if(flag) putchar(' ');
flag = true;
printf("%d", i + );
}
}
printf("\n");
} int main() {
scanf("%d", &n);
for(int i = ; i < n; ++i) cir[i].read();
for(int i = ; i < n; ++i) {
double t = / cir[i].c.length();
cir[i].c = cir[i].c * t;
cir[i].r = cir[i].r * t;
}
pcnt = ;
for(int i = ; i < n; ++i)
for(int j = i + ; j < n; ++j) pcnt += intersect(cir[i], cir[j], p[pcnt], p[pcnt + ]);
maxAns = ;
for(int i = ; i < n; ++i) {
int t = count(cir[i].c);
if(t > maxAns) {
maxAns = t;
ansVec = cir[i].c;
}
}
for(int i = ; i < pcnt; ++i) {
int t = count(p[i]);
if(t > maxAns) {
maxAns = t;
ansVec = p[i];
}
}
printf("%d\n", maxAns);
output(ansVec);
}
POJ 2177 Ghost Busters(三维几何)的更多相关文章
- POJ 2251 Dungeon Master --- 三维BFS(用BFS求最短路)
POJ 2251 题目大意: 给出一三维空间的地牢,要求求出由字符'S'到字符'E'的最短路径,移动方向可以是上,下,左,右,前,后,六个方向,每移动一次就耗费一分钟,要求输出最快的走出时间.不同L层 ...
- hdu 5839(三维几何)
Special Tetrahedron Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Othe ...
- POJ 2251 Dungeon Master (三维BFS)
题目链接:http://poj.org/problem?id=2251 Dungeon Master Time Limit: 1000MS Memory Limit: 65536K Total S ...
- poj 2031Building a Space Station(几何判断+Kruskal最小生成树)
/* 最小生成树 + 几何判断 Kruskal 球心之间的距离 - 两个球的半径 < 0 则说明是覆盖的!此时的距离按照0计算 */ #include<iostream> #incl ...
- poj 1185 炮兵阵地(三维状态压缩dP)
题目:http://poj.org/problem?id=1185 思路: d[i][j][k]表示第i行的状态为第k个状态,第i-1行的状态为第j个状态的时候 的炮的数量. 1表示放大炮, 地形状态 ...
- POJ 2252 Dungeon Master 三维水bfs
题目: http://poj.org/problem?id=2251 #include <stdio.h> #include <string.h> #include <q ...
- POJ 2653 Pick-up sticks(几何)
Pick-up sticks Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 13377 Accepted: 5039 D ...
- POJ 3304 Segments --枚举,几何
题意: 给n条线段,问有没有一条直线,是每条线段到这条直线上的投影有一个公共点. 解法: 有公共点说明有一条这条直线的垂线过所有线段,要找一条直线过所有线段,等价于从所有线段中任选两端点形成的直线存在 ...
- POJ 2318 TOYS && POJ 2398 Toy Storage(几何)
2318 TOYS 2398 Toy Storage 题意 : 给你n块板的坐标,m个玩具的具体坐标,2318中板是有序的,而2398无序需要自己排序,2318要求输出的是每个区间内的玩具数,而231 ...
随机推荐
- struts2-笔记
文件下载http://struts.apache.org/download.cgi 第一步导入jar 包 在lib中有jar 包,不能把这些都导入到项目中 在apps 目录里面,找到实例程序,程序中直 ...
- js浮点型,整型操作方法汇总(进行中)
浮点数操作方法如下: 1. Math.ceil()用作向上取整.(ceil 天花板) 2. Math.floor()用作向下取整. (floor 地板) (js 中取整底层原理是位运算的取反~运算,运 ...
- vue-cli使用swiper4在ie以及safari报错
vue-cli项目中,通过npm run swiper --save-dev安装的是swiper4版本的插件,这样安装以后在谷歌火狐等浏览器都可以正常运行,但是在safari浏览器(可能是版本太低)还 ...
- 19-3-4 Python进制转换;bool str int三者之间的转换;字符串的索引,切片;for循环的使用
进制转换: 二进制转十进制: 0010 1111 = 1*2**0+1*2**1+1*2**2+1*2**3+1*2**5 十进制转换二进制: 用十进制数除2逆序取余 --->101010 布 ...
- windows下MySQL免安装版配置教程mysql-8.0.12-winx64.zip版本
引用1:https://blog.csdn.net/weixin_42831477/article/details/81589325 引用2:https://blog.csdn.net/qq_3193 ...
- PHP 使用GD库合成带二维码的海报步骤以及源码实现
PHP 使用GD库合成带二维码的海报步骤以及源码实现 在做微信项目开发过程中,经常会遇到图片合成的问题,比如将用户的二维码合成到宣传海报中,那么,遇到这种情况,利用PHP的GD库也是很容易实现的,实现 ...
- Order Helper
using System; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Query; using Microsoft.Crm.Sdk.Messag ...
- 二、linux编译环境的搭建
1.linux编译工具安装 vim安装:apt-get install vim 注意:使用C语言源代码语法加亮功能,需要配置文件/etc/vim/vimrc,加入代码syntaxon.文件后缀必须为. ...
- STM32(13)——SPI
简介: SPI,Serial Peripheral interface串行外围设备接口. 接口应用在:EEPROM, FLASH,实时时钟,AD 转换器,还有数字信号处理器和数字信号解码器之间. 特点 ...
- Ruby中的类
初识ruby中的类 只需要简单的两行 class Point end 如果我们此时实例化一个类那么他会有一些自省(introspection)的方法 p = Point.new p.methodes( ...