UESTC1713(求两个圆的面积的交)

本文提供了一种计算两个圆相交部分面积的方法,并通过具体的示例进行了展示。该算法适用于给定圆心坐标和半径的情况。

无关青云路,无关诗书,无你处,无江湖

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
 

每个圆的属性可以使用三个参数来描述,xx-圆心横坐标,yy-圆心纵坐标,rr-半径,现给出两个圆分别的参数,求两个圆相交的面积。

Input

第一行是一个正整数TT(T12T≤12),表示有TT组测试数据 接下来有T行,每行有六个正整数描述两个圆的属性x1,y1,r1,x2,y2,r2x1,y1,r1,x2,y2,r2。 0x1,y1,r1,x2,y2,r25000≤x1,y1,r1,x2,y2,r2≤500

Output

对于每组测试数据输出一行,表示两个圆相交的面积大小,结果保留6位小数

Sample input and output

Sample Input Sample Output
3
0 0 10 15 0 10
-10 -10 5 0 -10 10
100 100 20 100 110 20
45.331175
35.076661
860.843690

Hint

By Qyitong

Source

2017 UESTC Training for Math


解题思路:直接求面积的交就行

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const double eps = 1e-10;
const double pi = acos(-1.0);
struct Point{
    double x, y;
    Point(double _x = 0, double _y = 0){
        x = _x;
        y = _y;
    }
};
typedef Point Vector;
Vector operator +(Vector A, Vector B) {return Vector(A.x + B.x, A.y + B.y);}//向量加
Vector operator -(Vector A, Vector B) {return Vector(A.x - B.x, A.y - B.y);}//向量减
Vector operator *(Vector A, double p) {return Vector(p * A.x, p * A.y);}//向量的数乘
Vector operator /(Vector A, double p) {return Vector(A.x / p, A.y / p);}//向量的数除
Vector operator -(Vector A) {return Vector(-A.x, -A.y);}//向量的取反
int dcmp(double x)
{
    if(fabs(x) < eps) return 0;
    else return x < 0 ? -1 : 1;
}
bool operator == (const Point& a, const Point& b) {
    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
double Cross(Vector A, Vector B)//求解向量叉积
{
    return A.x * B.y - A.y * B.x;
}
double Dot(Vector A, Vector B)//求解向量数量积
{
    return A.x * B.x + A.y * B.y;
}
double xmulti(Point p, Point a, Point b)//求向量pa叉乘pb
{
    return (a.x - p.x) * (b.y - p.y) - (a.y - p.y) * (b.x - p.x);
}
double getDis(Point p1, Point p2)
{
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
struct circle{
    Point p0;
    double r;
    circle(Point _p0 = Point(0, 0), double _r = 0){
        p0 = _p0;
        r = _r;
    }
};
int circle_loc(circle cc1, circle cc2)//判断两圆的位置关系,-1为包含(内切),0为相交,1为相离(外切)
{
    double d = getDis(cc1.p0, cc2.p0);
    double r1 = cc1.r;
    double r2 = cc2.r;
    double x1 = d - (r1 + r2);
    if(dcmp(x1) >= 0) return 1;
    double x2 = fabs(r1 - r2);
    double x3 = d - x2;
    if(dcmp(x3) <= 0) return -1;
    else return 0;
}
double area_circle(circle cc1, circle cc2)
{
    double d = getDis(cc1.p0, cc2.p0);
    double r1 = cc1.r;
    double r2 = cc2.r;
    int rala = circle_loc(cc1, cc2);
    if(rala == 1) return 0;
    if(rala == -1)
    {
        return (pi * min(r1, r2) * min(r1, r2));
    }
    double angle1 = acos((r1 * r1 + d * d - r2 * r2) / (2 * r1 * d));
    double angle2 = acos((r2 * r2 + d * d - r1 * r1) / (2 * r2 * d));
    double s = d * r1 * sin(angle1);
    double s1 = angle1 * r1 * r1;
    double s2 = angle2 * r2 * r2;
    return (s1 + s2 - s);
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        circle c1, c2;
        scanf("%lf%lf%lf%lf%lf%lf", &c1.p0.x, &c1.p0.y, &c1.r, &c2.p0.x, &c2.p0.y, &c2.r);
        printf("%.6lf\n", area_circle(c1, c2));
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值