Everything Has Changed (计算几何)

传送门

题意:

这个问题就是把相交的圆后多的弧线加上去,对大圆来说需要减一部分,对于小圆的部分需要加一段弧线,内切也算。

但是内含就不算了。最后题目交代了给出的圆一定是不会相交的。

题解:

今天多校的一道签到题,但是我没有签上道,后来我看了看dls的计算方法,居然和我的不一样。。。。。

后来我只是把计算的一部分改了改就A了,原因:要是用我的计算方法可能会丢失一点精度。

我的做法:

就是需要把相交的两个点连线,利用方程式求出这条线的表达式,后来代入点到直线的公式后得到d。

然后在它围着的三角形中   以圆的半径为斜边,以d为邻边,用acos(d / R)来计算。后来这种方法会丢失精度,

还需要加判断,因为相交的程度不同,表示的弧是不同的。if( d >= Dis( C1,C2 ) )时必须要换成另一边的弧。

但是这个方法的确是可以算出示例来,但是后来的数会出现精度丢失,所以很遗憾不能AC还爆零了。

正解:

我听了dls后的做法,我就试着改一小部分,看一看是不是我这样计算得到的答案会出问题。

扫描二维码关注公众号,回复: 2601834 查看本文章

居然还真是,不过我也很开心,因为自己能凭实力AC。

正解的方法是把圆心和相交的两个点连线,还需要把两个圆心连线。然后得到一个三角形,只要余弦定理计算即可。

所以,比赛时不能进入死胡同,本来自己就不太行,只要心态一崩肯定没戏。

我再附上图吧。

hhz

我的做法:错误方法:

#include<bits/stdc++.h>
using namespace std;
const double pi=acos(-1);
const double eps=1e-6;
int t=1;
double D(double x,double y,double A,double B,double C){
    double Fz=fabs(A*x+B*y+C);
    double Fm=fabs(  sqrt(A*A+B*B) ) ;
    return Fz/Fm;
}
double dis(double x1,double x2){
    return sqrt(x1*x1+x2*x2);
}
void solve(){
    int n;
    double R1,R2,x,y,ans=0;
    scanf("%d%lf",&n,&R1);
    ans=2*pi*R1;
    for(int i=1;i<=n;i++){
        scanf("%lf%lf%lf",&x,&y,&R2);
        double Dis=dis(x,y);
        if(fabs(R1-R2-Dis)<=(eps)){
            ans+=2*pi*R2;
        }else if(R1-R2<Dis&&Dis<R1+R2){
            double A=2*x,B=2*y,C=R2*R2-R1*R1-x*x-y*y;
            double d1=D(0,0,A,B,C);
            double d2=D(x,y,A,B,C);
            double Xita1=acos(d1/R1)*2;
            double Xita2=acos(d2/R2)*2;
            double L1=Xita1*R1,L2=Xita2*R2;
            if(d1>=Dis){
                L2=2*pi*R2-L2;
            }
            ans-=L1;
            ans+=L2;
        }
    }
    printf("%.6lf\n",ans);
}
int main()
{
    int T;
    for(scanf("%d",&T);t<=T;t++){
        solve();
    }
}

 正解:

#include<bits/stdc++.h>
using namespace std;
const double pi=acos(-1);
const double eps=1e-6;
int t=1;
double dis(double x1,double x2){
    return sqrt(x1*x1+x2*x2);
}
void solve(){
    int n;
    double R1,R2,x,y,ans=0;
    scanf("%d%lf",&n,&R1);
    ans=2*pi*R1;
    for(int i=1;i<=n;i++){
        scanf("%lf%lf%lf",&x,&y,&R2);
        double Dis=dis(x,y);
        if(fabs(R1-R2-Dis)<=(eps)){
            ans+=2*pi*R2;
        }else if(R1-R2<Dis&&Dis<R1+R2){
            double Xita1=acos( (R1*R1 + Dis*Dis-R2*R2) / (2*Dis*R1));
            double Xita2=acos( (R2*R2 + Dis*Dis-R1*R1) / (2*Dis*R2));
            double L1=Xita1*2*R1;
            double L2=Xita2*2*R2;
            ans-=L1;
            ans+=L2;
        }
    }
    printf("%.6lf\n",ans);
}
int main()
{
    int T;
    for(scanf("%d",&T);t<=T;t++){
        solve();
    }
}

猜你喜欢

转载自blog.csdn.net/Z_sea/article/details/81460757
今日推荐