acmclub 2081 班级聚会上的游戏

acmclub  2081  班级聚会上的游戏(天勤考研算法练习赛(5)

题目链接:http://zju.acmclub.com/index.php?app=problem_title&id=1&problem_id=2801

计算几何

题目分析:刨去内含和相离两种特殊情况,剩下的就是求两扇形面积和减去大四边形面积了。圆心角用反三角函数来求,精度是个坑。

code:

#include<stdio.h>
#include<math.h>
#define PI acos(-1)
int main()
{
	double c1,c2,r1,r2,c,h,x1,x2,y1,y2,p;
	while(scanf("%lf%lf%lf%lf%lf%lf",&x1,&y1,&r1,&x2,&y2,&r2)!=EOF)
	{
		c=sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
		if(r1<r2)h=r1,r1=r2,r2=h;//保证r1总是大的
		if(r1>=c+r2){printf("%.3f\n",PI*r2*r2);continue;}//内切||内含 
		if(r1+r2<=c){printf("0.000\n");continue;}//外切||相离 
		p=(r1+r2+c)/2;//海伦公式里的p,这用的海伦公式 
		h=sqrt(p*(p-r1)*(p-r2)*(p-c))*2/c;
		//printf("%f\n",h);
		c1=sqrt(r1*r1-h*h);
		c2=c-c1;
		if(r1*r1<r2*r2+c*c)
		printf("%.3f\n",asin(h/r1)*r1*r1+asin(h/r2)*r2*r2-c*h);
		else
		printf("%.3f\n",(PI-asin(h/r2))*r2*r2+asin(h/r1)*r1*r1-c*h);
		//double a1=acos((r1*r1+c*c-r2*r2)/(2.0*r1*c));
		//double a2=acos((r2*r2+c*c-r1*r1)/(2.0*r2*c));
		//printf("%.3f\n",a1*r1*r1+a2*r2*r2-r1*c*sin(a1));
	}
	return 0;
}

PS:我用的海伦公式求得面积,再通过面积求高;注释掉的那种方法用的是余弦定理直接求角,也能A。

PPS:一开始π定义的3.14159265,wrong死了,直到最后也没发现是wrong在这里,标程上定义的是acos(-1),能过,我后来又改成小数点后16位,也过了……

附标程:

#include <stdio.h>
#include <math.h>

const double eps = 1e-8;
const double pi = acos(-1);

double x[2], y[2], r[2];

double dis(double x1, double y1, double x2, double y2) {
        return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}

double fusiform(double a, double c, double b) {
        double angle = acos((a * a + b * b - c * c) / (2 * a * b)) * 2;
        double s1 = a * a * pi * (angle / (2 * pi));
        double s2 = a * a * sin(angle) / 2;
        return s1 - s2;
}

double common(double x1, double y1, double r1, double x2, double y2, double r2) {
        double d = dis(x1, y1, x2, y2);
        if (d + eps >= r1 + r2)
                return 0;
        if (d - eps <= fabs(r1 - r2)) {
                if (r1 > r2)
                        return pi * r2 * r2;
                else
                        return pi * r1 * r1;
        }
        return fusiform(r1, r2, d) + fusiform(r2, r1, d);
}

int main() {
        while (scanf("%lf%lf%lf%lf%lf%lf", &x[0], &y[0], &r[0], &x[1], &y[1], &r[1]) != EOF)
                printf("%.3lf\n", common(x[0], y[0], r[0], x[1], y[1], r[1]));
        return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值