题目链接:点击这里
题意: 平面上一个圆, 两个圆外的点A,B, 给A一个初速度, 问能否碰到B.
根据
A
的运行射线轨迹分成两种情况:
1. 如果运行时不撞到圆, 那么判断
2. 如果撞到圆, 求出比较近的那个交点
P
, 求出
trick:因为输入都是整数, 所以精度开的大一点.
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define maxn 100005
const double eps = 1e-5;
const double INF = 1e20;
const double pi = acos (-1.0);
int dcmp (double x) {
if (fabs (x) < eps) return 0;
return (x < 0 ? -1 : 1);
}
inline double sqr (double x) {return x*x;}
//*************点
struct Point {
double x, y;
Point (double _x = 0, double _y = 0):x(_x), y(_y) {}
void input () {scanf ("%lf%lf", &x, &y);}
void output () {printf ("%.2f %.2f\n", x, y);}
bool operator == (const Point &b) const {
return (dcmp (x-b.x) == 0 && dcmp (y-b.y) == 0);
}
bool operator < (const Point &b) const {
return (dcmp (x-b.x) == 0 ? dcmp (y-b.y) < 0 : x < b.x);
}
Point operator + (const Point &b) const {
return Point (x+b.x, y+b.y);
}
Point operator - (const Point &b) const {
return Point (x-b.x, y-b.y);
}
Point operator * (double a) {
return Point (x*a, y*a);
}
Point operator / (double a) {
return Point (x/a, y/a);
}
double len2 () {//返回长度的平方
return sqr (x) + sqr (y);
}
double len () {//返回长度
return sqrt (len2 ());
}
Point change_len (double r) {//转化为长度为r的向量
double l = len ();
if (dcmp (l) == 0) return *this;//零向量返回自身
r /= l;
return Point (x*r, y*r);
}
};
double cross (Point a, Point b) {//叉积
return a.x*b.y-a.y*b.x;
}
double dot (Point a, Point b) {//点积
return a.x*b.x + a.y*b.y;
}
double dis (Point a, Point b) {//两个点的距离
Point p = b-a; return p.len ();
}
//************直线 线段
struct Line {
Point s, e;//直线的两个点
double k;//极角
Line () {}
Line (Point _s, Point _e) {
s = _s, e = _e;
k = atan2 (e.y - s.y,e.x - s.x);
}
void input () {
s.input ();
e.input ();
}
void adjust () {
if (e < s) swap (e, s);
}
double length () {//求线段长度
return dis (s, e);
}
void get_angle () {
k = atan2 (e.y - s.y,e.x - s.x);
}
};
int relation (Point p, Line l) {//点和直线的关系
//1:在左侧 2:在右侧 3:在直线上
int c = dcmp (cross (p-l.s, l.e-l.s));
if (c < 0) return 1;
else if (c > 0) return 2;
else return 3;
}
bool point_on_seg (Point p, Line l) {//判断点在线段上
return dcmp (cross (p-l.s, l.e-l.s)) == 0 &&
dcmp (dot (p-l.s, p-l.e) <= 0);
//如果忽略端点交点改成小于号就好了
}
bool point_on_halfline (Point p, Line l) {//判断点在射线上
int id = relation (p, l);
if (id != 3) return 0;
return dcmp (dot (p-l.s, l.e-l.s)) >= 0;
}
double point_to_line (Point p, Line a) {//点到直线的距离
return fabs (cross (p-a.s, a.e-a.s) / a.length ());
}
Point projection (Point p, Line a) {//点在直线上的投影
return a.s + (((a.e-a.s) * dot (a.e-a.s, p-a.s)) / (a.e-a.s).len2() );
}
Point symmetry (Point p, Line a) {//点关于直线的对称点
Point q = projection (p, a);
return Point (2*q.x-p.x, 2*q.y-p.y);
}
//***************圆
struct Circle {
//圆心 半径
Point p;
double r;
Circle () {}
Circle (Point _p, double _r) : p(_p), r(_r) {}
Circle (double a, double b, double _r) {
p = Point (a, b);
r = _r;
}
void input () {
p.input ();
scanf ("%lf", &r);
}
void output () {
p.output ();
printf (" %.2f\n", r);
}
};
int relation (Line a, Circle b) {//直线和圆的关系
//0:相离 1:相切 2:相交
double p = point_to_line (b.p, a);
if (dcmp (p-b.r) == 0) return 1;
return (dcmp (p-b.r) < 0 ? 2 : 0);
}
int line_circle_intersection (Line v, Circle u, Point &p1, Point &p2) {//直线和圆的交点
//返回交点个数 交点保存在引用中
if (!relation (v, u)) return 0;
Point a = projection (u.p, v);
double d = point_to_line (u.p, v);
d = sqrt (u.r*u.r - d*d);
if (dcmp (d) == 0) {
p1 = a, p2 = a;
return 1;
}
p1 = a + (v.e-v.s).change_len (d);
p2 = a - (v.e-v.s).change_len (d);
return 2;
}
Circle c;
Point a, b, v;
Point p1, p2;
bool solve () {
Point aa = a+v;
Line pre = Line (a, aa);
int cnt = line_circle_intersection (pre, c, p1, p2);
if (cnt < 2) {
if (point_on_halfline (b, pre))
return 1;
else
return 0;
}
if (dis (p1, a) > dis (p2, a)) p1 = p2;
Line Seg (a, p1);
if (point_on_seg (b, Seg))
return 1;
Line faxian (p1, c.p);
aa = symmetry (a, faxian);
Line now (p1, aa);
if (point_on_halfline (b, now))
return 1;
return 0;
}
int main () {
int t, kase = 0;
scanf ("%d", &t);
while (t--) {
printf ("Case #%d: ", ++kase);
c.p.input (), scanf ("%lf", &c.r);
a.input (), v.input (), b.input ();
puts (solve () ? "Yes" : "No");
}
return 0;
}
/*
10
0 1 1
-1 0 1 0
100000 0
0 1 1
-1 0 1 1
5 5
0 1 1
0 -99 0 12345
0 -100
*/