您的位置:首页 > 产品设计 > UI/UE

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

2016-06-08 19:50 507 查看

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

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


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



他在一个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;
}
else
return 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+行搞定;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  计算几何