HDU 5572 An Easy Physics Problem(计算几何)

题意判断一个点a以一个速度发射,遇到圆会反弹,问给定点b是否在点a路径上

#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define double long double
using namespace std;
const int maxn = 1e5 + 10;
const double EPS = 1e-6;
int T, Case;
double rx, ry, r;
double sx, sy, vx, vy, tx, ty;
struct node{
	double x_1, y_1, x_2, y_2;
};
double dist(double x_1, double y_1, double x_2, double y_2){
	return sqrt((x_1-x_2)*(x_1-x_2)+(y_1-y_2)*(y_1-y_2));
}
node banana_cunzai(double c, double d, double r, double k, double b){//(x+c)^2+(x+d)^2=r^2
	double x_1 = -(sqrt((k*k+1)*r*r-c*c*k*k+(2*c*d+2*b*c)*k-d*d-2*b*d-b*b) + (d+b)*k+c)/(k*k+1);
	double y_1 = -(k*(sqrt(k*k*r*r+r*r-c*c*k*k+2*c*d*k+2*b*c*k-d*d-2*b*d-b*b)+c)+d*k*k-b)/(k*k+1);
	double x_2 = (sqrt((k*k+1)*r*r-c*c*k*k+(2*c*d+2*b*c)*k-d*d-2*b*d-b*b) + (-d-b)*k-c)/(k*k+1);
	double y_2 = -(k*(c-sqrt(k*k*r*r+r*r-c*c*k*k+2*c*d*k+2*b*c*k-d*d-2*b*d-b*b))+d*k*k-b)/(k*k+1);
	double d1 = dist(sx, sy, x_1, y_1);
	double d2 = dist(sx, sy, x_2, y_2);
	if(d1 > d2) swap(x_1, x_2), swap(y_1, y_2);
	return node{x_1,y_1,x_2,y_2};
}
node banana_bucun(double rx, double ry, double r, double sx){
	double x_1 = sx;
	double x_2 = sx;
	double y_1 = ry+sqrt(r*r-(sx-rx)*(sx-rx));
	double y_2 = ry-sqrt(r*r-(sx-rx)*(sx-rx));
	double d1 = dist(sx, sy, x_1, y_1);
	double d2 = dist(sx, sy, x_2, y_2);
	if(d1 > d2) swap(x_1, x_2), swap(y_1, y_2);
	return node{x_1,y_1,x_2,y_2};
}
bool check_dir(double x_1, double y_1, double x_2, double y_2){
	if(fabs(x_1*y_2 - x_2*y_1) < EPS && x_1*x_2 >= 0 && y_1*y_2 >= 0) return true;
	else return false;
}
double cosin(double x_1, double y_1, double x_2, double y_2){
    return (x_1*x_2+y_1*y_2) / (sqrt(x_1*x_1+y_1*y_1)*sqrt(x_2*x_2+y_2*y_2));
}
bool check_tan(double s_x, double s_y, double t_x, double t_y, double r_x, double r_y){\
    double x_1 = r_x - rx, y_1 = r_y - ry;
    if(fabs(cosin(x_1,y_1,tx-r_x,ty-r_y) - cosin(x_1,y_1,sx-r_x,sy-r_y)) < EPS && !check_dir(r_x-sx,r_y-sy,tx-sx,ty-sy)) return true;
    else return false;
}
double p_to_l(double x, double y, double v_x, double v_y, double s_x, double s_y){
    double A = v_y / v_x, B = -1; double C = s_y - A * sx;
    return fabs(A * x + B * y + C) / sqrt(A * A + B * B);
}
int main()
{
	scanf("%d", &T);
	while(T --){
		cin >> rx >> ry >> r >> sx >> sy >> vx >> vy >> tx >> ty;
		printf("Case #%d: ", ++Case);
		if(vx == 0){
			if(fabs(sx-rx) < r){ //与圆香蕉
				node temp = banana_bucun(rx, ry, r, sx);
				if(dist(sx,sy,temp.x_1,temp.y_1) - dist(sx,sy,tx,ty) > -EPS //指向⚪但是未香蕉
					&& check_dir(temp.x_1-sx,temp.y_1-sy,vx,vy) && check_dir(vx,vy,tx-sx,ty-sy)
				) cout << "Yes" << endl;
				else if(check_dir(-temp.x_1+sx,-temp.y_1+sy,vx,vy)) cout << "Yes" << endl;
                else if(check_tan(sx, sy, tx, ty, temp.x_1, temp.y_1)) cout << "Yes" << endl;
                else cout << "No" << endl;
			}
			else{
				double t_x = tx - sx, t_y = ty - sy;
				if(t_y  * vy >= 0 && t_x == 0) cout << "Yes" << endl;
				else cout << "No" << endl;
			}
		}
		else{
            if(p_to_l(rx, ry, vx, vy, sx, sy) >= r){//不相交
                if(check_dir(tx-sx,ty-sy,vx,vy)) cout << "Yes" << endl;
                else cout << "No" << endl;
            }
            else{
                double k = vy / vx; double b = sy - k * sx;
                node temp = banana_cunzai(-rx, -ry, r, k, b);//(x+c)^2+(x+d)^2=r^2
                if(dist(sx,sy,temp.x_1,temp.y_1) - dist(sx,sy,tx,ty) > -EPS  //指向⚪但是未香蕉
					&& check_dir(temp.x_1-sx,temp.y_1-sy,vx,vy) && check_dir(vx,vy,tx-sx,ty-sy)
				) cout << "Yes" << endl;
				else if(check_dir(-temp.x_1+sx,-temp.y_1+sy,vx,vy)) cout << "Yes" << endl;
                else if(check_tan(sx, sy, tx, ty, temp.x_1, temp.y_1)) cout << "Yes" << endl;
                else cout << "No" << endl;
            }
		}
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值