题意:
在一个平面坐标系中,有一个半径为R的圆
(R=10101010)
(
R
=
10
10
10
10
)
,其圆心在原点处。给出平面上N个点(N≤100),现在随机得到一个圆内的点,它会选择与它距离最近的一个点,(如果同时有多个,选择编号最小的一个),现在求给出的N个点中,每个点被选中的概率。
给出的点的坐标(x,y)满足
|x|,|y|≤106
|
x
|
,
|
y
|
≤
10
6
分析:
如果对极限的思想有一定的理解,那么这道题就变得非常非常水了,考虑到R极大,与给出点的坐标范围相比,就可以近似地看作是无限大。
这样一来,我们考虑求出给出点的凸包,凸包内部的面积相对于外部的无限大来说,可以忽略不计,所以我们可以忽略随机到凸包内部某点的情况。
我们发现,白色区域的面积相对于其他的面积来说,在极限的思想下,是可以忽略不计的,而当点位于同一种颜色时,总会选择同一个点(即区域前的字母)。这个区域的两条边分别于其相邻的,凸包上的边垂直。
在极限的思想下,要比较这几个区域的面积,我们只需要比较,凸包上某点与其对应区域所形成的角的大小。所以求出凸包后,在凸包上遍历一遍:
对凸包上的每个点,求出其相邻的两边的点积
(A⃗ ⋅B⃗ =|A|⋅|B|⋅cos<A⃗ ,B⃗ >)
(
A
→
⋅
B
→
=
|
A
|
⋅
|
B
|
⋅
cos
<
A
→
,
B
→
>
)
将这个值除以两边长,再取其相反数,即为我们要求的角的cos值,再用系统函数中的acos,就可以求出比例了。
(注意,这道题有点卡精度)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<cmath>
#define SF scanf
#define PF printf
#define MAXN 110
#define EPS 1e-7
using namespace std;
const double Pi=acos(-1);
struct node{
double x,y;
int id;
node(){}
node(double xx,double yy):x(xx),y(yy) {}
node operator + (const node &a) const {
return node(x+a.x,y+a.y);
}
node operator - (const node &a) const {
return node(x-a.x,y-a.y);
}
node operator * (const double &t) const {
return node(x*t,y*t);
}
double operator *(const node &a) const{
return x*a.x+y*a.y;
}
double operator ^(const node &a) const{
return x*a.y-y*a.x;
}
bool operator <(const node &a) const {
return fabs(y-a.y)<EPS?x<a.x:y<a.y;
}
}p[MAXN],l1[MAXN];
stack<node> s1,s;
double ans[MAXN];
int n,cnt1;
void solve(node a1[],int &cnt){
s.push(p[1]);
s1.push(p[1]);
s1.push(p[2]);
for(int i=3;i<=n;i++){
while(!s.empty()&&((p[i]-s.top())^(s1.top()-s.top()))<-EPS){
s.pop();
s1.pop();
}
s.push(s1.top());
s1.push(p[i]);
}
while(!s1.empty()){
a1[++cnt]=s1.top();
s1.pop();
}
while(!s.empty())
s.pop();
}
bool cmp(node a,node b){
return b<a;
}
double len(node a){
return sqrt(a.x*a.x+a.y*a.y);
}
pair<long long,long long> b[MAXN];
bool check(){
for(int i=1;i<=n;i++){
b[i].first=(long long)(p[i].x);
b[i].second=(long long)(p[i].y);
}
for(int i=2;i<n;i++){
long long xx1=b[i].first-b[i-1].first;
long long xx2=b[i+1].first-b[i].first;
long long yy1=b[i].second-b[i-1].second;
long long yy2=b[i+1].second-b[i].second;
if(yy1*xx2!=yy2*xx1)
return 0;
}
return 1;
}
int main(){
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
SF("%d",&n);
for(int i=1;i<=n;i++){
SF("%lf%lf",&p[i].x,&p[i].y);
p[i].id=i;
}
sort(p+1,p+1+n);
if(n==2){
PF("0.50000\n");
for(int i=2;i<n;i++)
PF("0.00000\n");
PF("0.50000\n");
return 0;
}
solve(l1,cnt1);
sort(p+1,p+1+n,cmp);
cnt1--;
solve(l1,cnt1);
cnt1--;
for(int i=1;i<=cnt1;i++){
int las,nxt;
if(i==1)
las=cnt1;
else
las=i-1;
if(i==cnt1)
nxt=1;
else
nxt=i+1;
double d=((l1[nxt]-l1[i])*(l1[las]-l1[i]))/(len(l1[nxt]-l1[i])*len(l1[las]-l1[i]));
//PF("[%lf]",fabs((l1[nxt]-l1[i])*(l1[i]-l1[las])));
d=acos(-d);
ans[l1[i].id]=d/(2.0*Pi);
}
for(int i=1;i<=n;i++)
PF("%.20lf\n",ans[i]);
}