Poj 3819 // Hdu 3425 Coverage

来源:互联网 发布:文字输出源码 编辑:程序博客网 时间:2024/05/22 08:34

//题意:求n个圆覆盖一条线段的百分比

//一开始没有处理0个圆相交的提前结束, 结果WA了无数次。。 

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
struct Point{double x, y;}sp, ep, c;
struct Line{double a, b, c;}l;
struct Unit{double s, e;}u[101];
double max(double t1, double t2){
    return t1>t2?t1:t2;
}
double min(double t1, double t2){
    return t1<t2?t1:t2;
}
double dist(Point p1, Point p2){
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
Line makeline(Point p1, Point p2){
    Line t1;
    int sign=1;
    t1.a=p2.y-p1.y;
    if(t1.a<0){
        t1.a*=-1;
        sign=-1;
    }
    t1.b=sign*(p1.x-p2.x);
    t1.c=sign*(p1.y*p2.x-p1.x*p2.y);
    return t1;
}
Point vert_p(Point p1, Line l1){
    Point p2;
    p2.x=(l1.b*(l1.b*p1.x-l1.a*p1.y)-l1.a*l1.c)/(l1.a*l1.a+l1.b*l1.b);
    p2.y=(l1.a*(l1.a*p1.y-l1.b*p1.x)-l1.b*l1.c)/(l1.a*l1.a+l1.b*l1.b);
    return p2;
}
int between(Point p1){
    if(p1.x<=max(sp.x, ep.x)&&p1.x>=min(sp.x, ep.x)&&
       p1.y<=max(sp.y, ep.y)&&p1.y>=min(sp.y, ep.y))
       return 0;
    if((sp.x-p1.x)*(ep.x-sp.x)>=0&&(sp.y-p1.y)*(ep.y-sp.y)>=0)
       return -1;
       return 1;
}
bool cmp(Unit u1, Unit u2){
    return u1.s<u2.s||(u1.s==u2.s&&u1.e<u2.e);
}
int main(){
    int n, i, sum;
    double d, r, h, dr, ds, ans, left, right;
    while(scanf("%d", &n)&&n){
        sum=0;ans=0;
        scanf("%lf%lf%lf%lf", &sp.x, &sp.y, &ep.x, &ep.y);
        l=makeline(sp, ep);
        d=dist(sp, ep);
        for(i=0; i<n; i++){
            scanf("%lf%lf%lf", &c.x, &c.y, &r);
            Point p=vert_p(c, l);
            h=dist(p, c);
            dr=sqrt(r*r-h*h);
            ds=dist(p, sp);
            if(h>r)continue;
            if(between(p)==0){
                if(ds-dr<0)
                u[sum].s=0;
                else u[sum].s=ds-dr;
                if(ds+dr>d)
                u[sum].e=d;
                else u[sum].e=ds+dr;
                sum++;
            }
            else if(between(p)==-1){
                if(ds>=dr)continue;
                u[sum].s=0;
                if(dr-ds>d)
                u[sum].e=d;
                else
                u[sum].e=dr-ds;
                sum++;
            }
            else {
                if(ds-d>=dr)continue;
                if(ds-dr<=0)
                u[sum].s=0;
                else u[sum].s=ds-dr;
                u[sum].e=d;
                sum++;
            }
        }
        if(sum==0){printf("0.00\n");continue;}     //少了这一句,WA了无数次。。
        sort(u, u+sum, cmp);
        left=u[0].s;right=u[0].e;
        for(i=1; i<sum; i++){
            if(u[i].s>right){
                ans+=(right-left);
                left=u[i].s;
                right=u[i].e;
            }
            else if(u[i].e>right)
            right=u[i].e;
        }
        ans=(ans+right-left)/d;
        printf("%.2f\n", 100*ans);
    }
    return 0;
}

原创粉丝点击