2016 UESTC Training for Math Problem E- 蹲在墙角画圈圈的愚人王

来源:互联网 发布:大数据实际应用案例 编辑:程序博客网 时间:2024/04/18 21:28

E - 蹲在墙角画圈圈的愚人王

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

愚人王发现自己也就是条咸鱼了,只能搞(出)搞(出)套路题了。所以膜拜了下final柱后,默默的蹲在墙角画圈圈去了.....

title

他在一个X*Y的矩形框框里画了n个圈圈(圆),然后无聊的向这个矩形中丢石子玩.....

突然,他灵(临)光(时)一(脑)闪(抽)!

他突然非常想知道,如果每次丢一个石子得到的分数为被覆盖的圆的数量的平方的话,那么得到的分数的数学期望是啥?!

嗯,他假设:石子是无限小的一个个的点;X,Y,圆的坐标和半径都是整数;所有的圆都在矩形框框中。

脑补半响后,他惊呼:“这道题太难了,根本不会做呀......“

机智的您,请帮愚人王解决一下这个问题吧.....

Input

第一行,n表示圈圈的个数。

0<=n<=1000;

第二行,X,Y

1<=X,Y<=1000

后面n行,每行三个整数x y r表示第i个圆的圆心坐标和半径。保证圆在矩形内部。

Output

一行,表示分数的期望。没有spj,结果请保留三位小数.

解题思路:

解题思路:

期望=每个区域覆盖次数的平方*(区域面积/总面积);

利用二次项展开,例如:(A+B+C)^2=(A*A+B*B+C*C+A*B+B*A+A*C+C*A+B*C+C*B);

乘号代表面积求交;我们可以发现这样计算每个区域的面积正好被计算了被覆盖次数的平方次;

代码:

#include<bits/stdc++.h>using namespace std;struct node{int x,y,r;}cir[1001];//保存圆的圆心坐标,半径; double cross(int x1,int y1,int r1,int x2,int y2,int r2)//求圆面积交,其中用到余弦定理,算出两个扇形的和减去多边形的面积; {double d=pow(x1-x2,2)+pow(y1-y2,2);if(d<=pow(r1-r2,2)){return pow(min(r1,r2),2)*M_PI;}else if(d>pow(r1-r2,2)&&d<pow(r1+r2,2)){double m1=(r1*r1+d-r2*r2)/(2*r1*sqrt(d));double m2=(r2*r2+d-r1*r1)/(2*r2*sqrt(d));double s1=acos(m1)*r1*r1;double s2=acos(m2)*r2*r2;double s3=sqrt(d)*r1*sin(acos(m1));return s1+s2-s3;}elsereturn 0;}int main(){int n,x,y,i,j;double sum=0;scanf("%d%d%d",&n,&x,&y);for(i=0;i<n;i++)scanf("%d%d%d",&cir[i].x,&cir[i].y,&cir[i].r);for(i=0;i<n;i++)for(j=0;j<n;j++)sum+=cross(cir[i].x,cir[i].y,cir[i].r,cir[j].x,cir[j].y,cir[j].r);//枚举求交; printf("%.3f",sum/(x*y));}

原本还想用圆的离散化的,那样太麻烦了,其实这样做30+行搞定;

0 0