#计算几何#POJ1375 UVA313 Intervals
分析
实际上就是 \((bx,by)\) 向圆作切线与 \(x\) 轴的交点形成一段区间,相当于变成了输出区间的并。
那么怎么把交点求出来呢,其实可以用解析几何来做,设切线方程为 \(x=m(y-by)+bx\),那么 \((cx,cy)\) 到该直线的距离为 \(r\)
也就是 \(\frac{|(cx-bx)-m(cy-by)|}{\sqrt{1+m^2}}=r\),转化为一元二次方程后直接套求根公式把两个根 \(m_1,m_2\) 求出来,那么交点横坐标就是 \(bx-m\cdot by\)
代码
#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long double ld;
int n; pair<ld,ld>a[511];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
bool cmp(pair<ld,ld> x,pair<ld,ld> y){
if (x.first!=y.first) return x.first<y.first;
else return x.second>y.second;
}
int main(){
while (n=iut()){
ld X=iut(),Y=iut();
for (int i=1;i<=n;++i){
ld x=iut(),y=iut(),r=iut();
ld A=(y-Y)*(y-Y)-r*r;
ld B=-2*(x-X)*(y-Y);
ld C=(x-X)*(x-X)-r*r;
ld sqrtdelta=sqrt(B*B-4*A*C);
ld L=(-B+sqrtdelta)/(2*A),R=(-B-sqrtdelta)/(2*A);
L=X-L*Y,R=X-R*Y;
if (L>R) swap(L,R);
a[i]=make_pair(L,R);
}
sort(a+1,a+1+n,cmp);
ld lst=a[1].first,Lst=lst;
for (int i=1;i<=n;++i){
if (a[i].second<=lst) continue;
if (lst<a[i].first){
printf("%.2Lf %.2Lf\n",Lst,lst);
Lst=a[i].first;
}
lst=a[i].second;
}
if (Lst<lst) printf("%.2Lf %.2Lf\n",Lst,lst);
putchar(10);
}
return 0;
}

浙公网安备 33010602011771号