HDU 6354--Everything Has Changed(判断两圆关系+弧长计算)

  • 题目
  • 题意:首先给定一个以原点为圆心,R为半径的圆,之后在给m个圆,这些圆可能会和原来的圆有所交集,计算开始的圆剩余区域的周长,不包括内部周长。
  • 首先判定两圆关系,如果内含,直接加上圆的周长,如果相交,在计算对应弧长,其他情况都不用计算。在计算圆心角的时候,有个精度问题,只用本身半径算出来的弧度会不够,所有用上两个圆的半径。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
const double PI = acos(-1.0);
typedef struct point {
    double x;
    double y;
    point() {

    }
    point(double a, double b) {
        x = a;
        y = b;
    }
    point operator -(const point &b)const {     //返回减去后的新点
        return point(x - b.x, y - b.y);
    }
    point operator +(const point &b)const {     //返回加上后的新点
        return point(x + b.x, y + b.y);
    }
    //数乘计算
    point operator *(const double &k)const {    //返回相乘后的新点
        return point(x * k, y * k);
    }
    point operator /(const double &k)const {    //返回相除后的新点
        return point(x / k, y / k);
    }
    double operator ^(const point &b)const {    //叉乘
        return x*b.y - y*b.x;
    }
    double operator *(const point &b)const {    //点乘
        return x*b.x + y*b.y;
    }
    double len() {      //返回直角三角形的斜边长
        return hypot(x, y);
    }
}point;
typedef struct circle {//圆
    double r;
    point centre;
    circle() {

    }
    circle(point a,double b) {
        centre = a;
        r = b;
    }
    double len() {
        return 2 * PI*r;
    }
    double area() {
        return PI*r*r;
    }
}circle;
circle  org;
double ans, r;
int t, m;
double dist(point p1, point p2) {       //返回平面上两点距离
    return sqrt((p1 - p2)*(p1 - p2));
}
int CircleInterNum(circle a, circle b) {
    double fh = fabs(a.r + b.r), fc = fabs(a.r - b.r), d = dist(a.centre, b.centre);
    if (d>fh)
        return -2;  //外离,没有交点
    if (d==fh)
        return -1;  //外切,一个交点
    if (d > fc&&d < fh)
        return 0;   //相交,两个交点
    if (d == fc)
        return 1;   //内切,一个交点
    if (d < fc&&d>=0)
        return 2;   //内含,没有交点
}

void CircleIntteLen(circle a, circle b) {
    double d = dist(a.centre, b.centre);
    double t = (d*d + a.r*a.r - b.r*b.r) / (2.0 * d);
    double h = sqrt((a.r*a.r) - (t*t))*2;
    double angle_a = 2*acos((a.r*a.r +d*d-b.r*b.r) / (2.0 * a.r*d));    //余弦公式计算圆心角,反三角计算出的是弧度
    double angle_b = 2*acos((b.r*b.r +d*d-a.r*a.r) / (2.0 * b.r*d));
    double la = angle_a*a.r;
    double lb = angle_b*b.r;
    ans += (lb-la);
}
int main(void) {
    cin >> t;
    while (t-- > 0) {
        org.centre = point(0, 0);
        cin >> m >> r;
        org.r = r;
        ans = org.len();
        double x, y, rt;
        for (int i = 0; i < m; i++) {
            cin >> x >> y >> rt;
            circle tmp = circle(point(x, y), rt);
            if (CircleInterNum(org, tmp) == 0)
                CircleIntteLen(org, tmp);
            if (CircleInterNum(org, tmp) == 1)
                ans += tmp.len();
        }
        printf("%.15f\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/FlyerBird/p/9431703.html
今日推荐