ZOJ 3058 Circle and Ring【圆与环相交面积】【圆与圆相交面积模板】

本文介绍了一个算法问题,即如何计算一个圆与一个圆环相交的面积。通过对不同情况的分析,提供了完整的C++代码实现,包括圆与圆环的相交判断、计算相交面积的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Circle and Ring

Time Limit: 1 Second      Memory Limit: 32768 KB

Given a circle and a ring, your task is to calculate the area of their intersection.

Input

This problem contains multiple test cases, process to the end of file.

For each case, there are two lines. The first line contains three real numbers x'y' and r' (0 <= r' <= 1024) representing the circle. The second line contains four real numbers xyr and R (0 <= r <= R <= 1024) representing the ring.

Output

For each case, output the area with the accuracy of three digits after decimal point in a signal line.

Never output "-0.000"!

Sample Input

10 0 20
-10 0 10 20
20 30 15
40 30 0 30

Sample Output

351.041
608.366

Author: WU, Zejun
Source: ZOJ Monthly, November 2008

题意:给出一个圆的圆心坐标和半径,以及一个圆环的坐标和内外圆的半径,求这个圆和圆环的相交面积。

经分析可得,一共有如下几种情况:

通过计算可得出:

圆和圆环的相交面积 = 圆和圆环中大圆的相交面积 - 圆和圆环中小圆的相交面积。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
const int maxn = 100010;
const double pi = acos(-1.0);

struct point {
	double x, y;
};

double x1, y11, r1, x2, y2, r2, R2;

double D(point a, point b)	//两点间距离
{
	return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}

double calc(point a, double r1, point b, double r2)	//计算面积
{
	double d = D(a, b);
	double cosaa = (r1*r1 + d*d - r2*r2) / (2 * r1*d);
	double cosa = acos(cosaa);
	double l = r1*cosa * 2;
	double s = l*r1 / 2;
	double s2 = r1*r1*sin(cosa)*cos(cosa);
	return s - s2;
}

bool ainb(point a, double r1, point b, double r2)	//判断a是否在b中
{
	double d = D(a, b);
	if (d <= r2 - r1) return 1;
	return 0;
}

bool ainstb(point a, double r1, point b, double r2)	//判断a和b是否有相交的区域
{
	double d = D(a, b);
	if (d >= fabs(r1 - r2) && d <= r1 + r2)
		return 1;
	return 0;
}

double S(point a, double r1, point b, double r2)	//计算相交面积
{
	if (ainb(a, r1, b, r2))
		return pi*r1*r1;
	if (ainb(b, r2, a, r1))
		return pi*r2*r2;
	if (!ainstb(a, r1, b, r2)) return 0;
	return calc(a, r1, b, r2) + calc(b, r2, a, r1);
}



int main()
{
	point a, b;
	double r1, r2, r3;
	while (~scanf("%lf%lf%lf", &a.x, &a.y, &r1))
	{
		scanf("%lf%lf%lf%lf", &b.x, &b.y, &r2, &r3);
		printf("%.3f\n", S(a, r1, b, r3) - S(a, r1, b, r2));
	}
	return 0;
}




转载于:https://www.cnblogs.com/Archger/p/8451592.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值