题意:
有N座城市,M个乡村,初始状态下乡村与城市之间没有任何边相连,现在需要将每个乡村都与城市相连。连接方式是:
随机选择一个未连接的乡村,将其与最近的已经与城市相连的点连接(即城市或已连接城市的乡村)
代价即为这两个点的直线距离。
求最终代价的期望值。
N,M≤50
N
,
M
≤
50
分析:
对于这类每个点都会参与计算的题目,应该要很快想到主要方式应该为计算贡献。
我们考虑每个乡村的代价:很显然,对于一个乡村
u
u
,若存在另一个乡村使得
dist(u,v)
d
i
s
t
(
u
,
v
)
可能会造成贡献,必然满足
dist(u,v)<与u最近的城市的到u的距离
d
i
s
t
(
u
,
v
)
<
与
u
最
近
的
城
市
的
到
u
的
距
离
。
再来看连接的方式:每次都是随机连接,所以很显然最终任意一组排列都是等可能的方案。
所以如果一个点对
(u,v)
(
u
,
v
)
的距离被计算,则其必然满足所有到u的距离小于v的点在排列中均在v点之后。
假设要满足有特定的k个点在排列中位于v之后,则概率为:
由于本题数据过小,这样臃肿的计算公式也可以跑过,所以我就懒得化简了
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 55
using namespace std;
pair<double,double> c[MAXN],v[MAXN];
double pos[MAXN],t[MAXN],ans;
bool used[MAXN];
int n,m;
double get_pos(int k){
double res=0;
for(int i=m-k-1,j=1;i>=0;i--,j++)
res+=(t[m-k-1]*t[m-j])/(t[m]*t[i]);
return res;
}
void prepare(){
t[0]=1;
for(int i=1;i<=m;i++)
t[i]=t[i-1]*double(i);
for(int i=1;i<=m;i++)
pos[i]=get_pos(double(i));
}
long long dist2(pair<double,double> a,pair<double,double> b){
long long x2=(long long)(a.first);
long long y2=(long long)(a.second);
long long x3=(long long)(b.first);
long long y3=(long long)(b.second);
return (x3-x2)*(x3-x2)+(y3-y2)*(y3-y2);
}
double dist(pair<double,double> a,pair<double,double> b){
double res1=double(dist2(a,b));
return sqrt(res1);
}
class KingdomXCitiesandVillages{
public:
double determineLength(vector<int> r1,vector<int> r2,vector<int> r3,vector<int> r4){
//SF("%d%d",&n,&m);
n=r1.size(),m=r3.size();
prepare();
for(int i=0;i<n;i++){
//SF("%lf",&c[i].first);
c[i].first=double(r1[i]);
}
for(int i=0;i<n;i++){
//SF("%lf",&c[i].second);
c[i].second=double(r2[i]);
}
for(int i=0;i<m;i++){
//SF("%lf",&v[i].first);
v[i].first=double(r3[i]);
}
for(int i=0;i<m;i++){
//SF("%lf",&v[i].second);
v[i].second=double(r4[i]);
}
for(int i=0;i<m;i++){
int minid,minid1,cnt=0;
double p=1;
memset(used,0,sizeof used);
used[i]=1;
minid1=-1;
for(int j=0;j<n;j++)
if(minid1==-1||dist2(v[i],c[j])<dist2(v[i],c[minid1]))
minid1=j;
while(1){
minid=-1;
for(int j=0;j<m;j++)
if(used[j]==0&&(minid==-1||dist2(v[i],v[j])<dist2(v[i],v[minid])))
minid=j;
if(minid==-1||dist2(v[i],v[minid])>dist2(v[i],c[minid1])){
ans+=dist(v[i],c[minid1])*p;
//PF("[%d %lf %lf]\n",i,p,dist(v[i],c[minid1]));
break;
}
double p1=p*pos[cnt+1];
//PF("[%d %lf %lf]\n",i,p1,dist(v[i],v[minid]));
ans+=dist(v[i],v[minid])*p1;
p-=p1;
cnt++;
used[minid]=1;
}
}
return ans;
}
};