POJ 2546 Circular Area [相交园面积]【计算几何】

题目链接:http://poj.org/problem?id=2546

Circular Area
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 5662 Accepted: 2215
Description

Your task is to write a program, which, given two circles, calculates the area of their intersection with the accuracy of three digits after decimal point.
Input

In the single line of input file there are space-separated real numbers x1 y1 r1 x2 y2 r2. They represent center coordinates and radii of two circles.
Output

The output file must contain single real number - the area.
Sample Input

20.0 30.0 15.0 40.0 30.0 30.0
Sample Output

608.366


题目大意:
就是求两个圆的相交部分的面积

解题思路:
就是简单的几何题目。
两个圆的位置一共有五种情况
1.内含 2.内切 3.相交 4.外切 5.外离
在计算几何中 内含与内切 可以当做同一种情况 外切与外离 可以当做同一种情况
Ps:如果有疑问可以自己画一画图 就会明白了

所以在计算几何中只要分成3种情况就行了
先定义 d为两圆圆心距离

1.外离
外离

这种情况下d>=r1+r2
两圆间没有相交的部分
所以相交面积是0

2.内含

内含
这种情况下 大圆把小圆全部覆盖
相交的面积就是校园的面积 PI * r1 * r1
此情况下 d<=r大-r小
写成代码就是d <= fabs(r1 - r2)

3.相交
相交

相交的部分可以分成 大小两个圆上弧ab与直线ab围成的图形
即可看作
S扇形abc1-S△abc1+S扇形abc2-S△abc2<=>
S扇形abc1+S扇形abc2-S□ac1bc2;
根据中学学的扇形的面积公式可以推到如下

ang1 = acos((r1 * r1 + d * d - r2 * r2) / 2. / r1 / d)
ang2 = acos((r2 * r2 + d * d - r1 * r1) / 2. / r2 / d)
S扇形abc1=ang1 * r1 * r1
S扇形abc2=ang2 * r2 * r2
S□ac1bc2=d * r1 * sin(ang1)

S = ang1 * r1 * r1+ang2 * r2 * r2 - d * r1 * sin(ang1)


附本题代码

#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <cmath>  
#include <algorithm>  
using namespace std;  
#define repf(i,a,b) for(int i=(a);i<=(b);i++)  

typedef long long ll;  
const double PI = 3.141592653;  

struct Round {  
    double x, y;  
    double r;  
} r[2];  

double dis(Round a, Round b) {  
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));  
}  

double solve(Round a, Round b) {  
    double d = dis(a, b);  
    if (d >= a.r + b.r)  
        return 0;  
    if (d <= fabs(a.r - b.r)) {  
        double r = a.r < b.r ? a.r : b.r;  
        return PI * r * r;  
    }  
    double ang1 = acos((a.r * a.r + d * d - b.r * b.r) / 2. / a.r / d);  
    double ang2 = acos((b.r * b.r + d * d - a.r * a.r) / 2. / b.r / d);  
    double ret = ang1 * a.r * a.r + ang2 * b.r * b.r - d * a.r * sin(ang1);  
    return ret;  
}  

int main() {  
    while (~scanf("%lf%lf%lf%lf%lf%lf", &r[0].x, &r[0].y, &r[0].r, &r[1].x, &r[1].y, &r[1].r)) {  
        printf("%.3f\n", solve(r[0], r[1]));  
    }  
    return 0;  
}  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值