poj 3819
给出一条线段的两个端点,再给出n个圆,求出这条线段被所有圆覆盖的部分占了整条线段的百分比。
圆与线段的交点 :
向量AB 的参数方程 P = A + t * (B - A) 0<=t<=1 ;
将点带入圆的方程即可。
注意:
有交点 0 <= t <= 1 ;
此题求覆盖的部分。 则 若求得 t 满足 ;
double ask(double t){
if(t < 0) return 0 ;
if(t > 1) return 1 ;
return t ;
}
const double eps = 1e-8 ;
int dcmp(double x){
if(fabs(x) < eps) return 0 ;
if(x < eps) return -1 ;
return 1 ;
}
struct point{
double x , y ;
void mycin(){
cin>>x>>y ;
}
};
double ask(double x){
if(x < 0) return 0 ;
if(x > 1) return 1 ;
return x ;
}
vector<pair<double , double> > g ;
void circle_cross_line(point a , point b , point o , double r){
double x0 = o.x , y0 = o.y ;
double x1 = a.x , y1 = a.y ;
double x2 = b.x , y2 = b.y ;
double dx = x2 - x1 , dy = y2 - y1 ;
double A = dx * dx + dy * dy ;
double B = 2.0 * dx * (x1 - x0) + 2.0 * dy * (y1 - y0) ;
double C = (x1-x0) * (x1-x0) + (y1-y0) * (y1-y0) - r * r ;
double delta = B * B - 4 * A * C ;
if(dcmp(delta) >= 0){
double t1 = (-B - sqrt(delta)) / (2.0*A) ;
double t2 = (-B + sqrt(delta)) / (2.0*A) ;
double L = ask(t1) ;
double R = ask(t2) ;
if(L > R) swap(L , R) ;
g.push_back( make_pair( L , R) ) ;
}
}
point o , a , b ; double r ;
int main(){
int n , i , j , k ;
while(cin>>n && n){
g.clear() ;
a.mycin() ; b.mycin() ;
for(i = 1 ; i <= n ; i++){
o.mycin() ; cin>>r ;
circle_cross_line(a , b , o , r) ;
}
if(g.size() == 0){
puts("0.00") ; continue ;
}
sort(g.begin() , g.end()) ;
double L = g[0].first , R = g[0].second , ans = 0.0 ;
for(i = 1 ; i < g.size() ; i++){
if(g[i].first > R){
ans += R - L ;
L = g[i].first ;
R = g[i].second ;
}
else R = max(R , g[i].second) ;
}
ans += R - L ;
printf("%.2lf\n" , ans * 100.0) ;
}
return 0 ;
}