2022HDU多校第2场D

题目大意:空间上,给定两个圆环满足最小距离条件至少0.1,求两个圆环是否连在一起(就像锁链一样)。

 

两个圆环连在一起,有点像这样的性质,也即一个平面分别交两个圆环于两点,则这四个点有依次的感觉。用一个更加准确的判断条件来说,就是两个圆环分别所在的平面交于唯一一条直线(也许没有),我们需要判断的是两个圆环在该直线上的四个交点是否是交错的(也许不够四个),那么什么叫做交错的呢?我们知道直线可以表达为线性的参数方程形式,使用这种形式表达出来的点关于参数t具有方向性,那么所谓四交点交错,也即四参数t的交错。令两个圆环关于直线的交点分别为t11,t12,t21,t22则交错的具体表达形式就是(t11-t21)*(t11-t22)*(t12-t21)*(t12-t22)<0(为什么不等于0?)。

 

接下来的问题是如何求直线与圆环的交。或许这样的问题略显麻烦,但是我们需要的其实是求取已经在同一个平面上的直线与圆环的交罢了。那么我们可以把模型退化成直线与球的交,这样的问题永远都是便于求解的,并且,共平面的性质也能保证有效性。

 

那么我们需要计算的仅仅只是计算平面交表达式的方法以及计算直线关于球的交的方法罢了。而这些不过是计算几何需要的基本技能而已,所以直接上代码。

 

// #include<bits/stdc++.h>
#include<iostream>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
typedef long double lb;

#define vc    vect3
#define c     const
#define cv(x) const vect3& x
#define op(t) operator t

struct vect3{
	lb x,y,z;
	void get(){cin>>x>>y>>z;}
	void put(){cout<<x<<' '<<y<<' '<<z<<' '<<endl;}
	lb dot(const vect3&t)const{
		return x*t.x+y*t.y+z*t.z;
	}
	lb len()const{
		return sqrt(dot(*this));
	}
	vect3 cross(cv(t))c{
		return {
			y*t.z-z*t.y,
			z*t.x-x*t.z,
			x*t.y-y*t.x
		};
	}
	void unit(){
		lb l=len();
		x/=l,y/=l,z/=l;
	}
	vc op(+)(cv(t))c{
		return {x+t.x,y+t.y,z+t.z};
	}
	vc op(-)(cv(t))c{
		return {x-t.x,y-t.y,z-t.z};
	}
	vc op(*)(lb t)c{
		return {x*t,y*t,z*t};
	}
};

struct cir{
	vc cent;
	vc leg;
	lb R;
	void get(){cent.get();leg.get();cin>>R;}
	void put(){cent.put();leg.put();cout<<R<<endl;}
};

vc cross_dir(cir&a,cir&b){
	return a.leg.cross(b.leg);
}

vector<vc> pus(cir&a,cir&b){
	vc t=cross_dir(a,b);
	// t.put();
	return vector<vc>({t,t.cross(a.leg),t.cross(b.leg)});
}

vector<vc> lin(cir&a,cir&b){
	auto t=pus(a,b);
	lb x=t[1].dot(b.leg);
	lb y=b.cent.dot(b.leg)-a.cent.dot(b.leg);
	return vector<vc>({a.cent+t[1]*(y/x),t[0]});
}

vector<lb> getp(vc&ori,vc&to,cir&cl){
	lb A=to.dot(to);
	auto p=ori-cl.cent;
	lb B=2*to.dot(p);
	lb C=p.dot(p)-cl.R*cl.R;
	lb Z;
	if((Z=B*B-4*A*C)<0) return vector<lb>({});
	Z=sqrt(Z);
	return vector<lb>({(-B+Z)/(2*A),(-B-Z)/(2*A)});
}

void work(){
	cir x,y;
	x.get();
	y.get();
	auto t=lin(x,y);
	// t[0].put();
	// t[1].put();
	t[1].unit();
	auto a1=getp(t[0],t[1],x);
	auto a2=getp(t[0],t[1],y);
	if(a1.size()!=2){
		cout<<"No"<<endl;
		return;
	}
	if(a2.size()!=2){
		cout<<"No"<<endl;
		return;
	}
	if((a1[0]-a2[0])*(a1[0]-a2[1])*(a1[1]-a2[0])*(a1[1]-a2[1])>1E-8){
		cout<<"No"<<endl;
		return;
	}
	// cout<<a1[0]<<' '<<a1[1]<<endl;
	// cout<<a2[0]<<' '<<a2[1]<<endl;
	cout<<"Yes"<<endl;
}

int main(){
	int T;
	cin >> T;
	while(T--){
		work();
	}
}

  

posted @ 2022-07-22 18:38  Harudesuyo  阅读(62)  评论(0)    收藏  举报