题目链接:点击这里
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<deque>//代码写的有点丑
#include<cmath>
using namespace std;
const double pi=acos(-1.0);
double kkk[2005][105];
double ctr[105];
double disr[2005];
int main(){
int n,m;
double r;
scanf("%d%d",&n,&m);scanf("%lf",&r);
for(int i=1;i<=n;++i) scanf("%lf",&ctr[i]);
for(int i=1;i<=m;++i) for(int j=1;j<=n;++j) scanf("%lf",&kkk[i][j]);
for(int i=1;i<=m;++i){
double ans=0;
for(int j=1;j<=n;++j){
ans+=(double)((kkk[i][j]-ctr[j])*(kkk[i][j]-ctr[j]));
}
disr[i]=sqrt(ans);
}
for(int i=1;i<=m;++i){
double iui=0;
for(int j=1;j<=m;++j){//这里开数组记录的话可以少跑一半的复杂度,我偷懒了。。。
if(i==j) continue;
double diss=0;
for(int k=1;k<=n;++k){
diss+=(double)((kkk[i][k]-kkk[j][k])*(kkk[i][k]-kkk[j][k]));
}
diss=sqrt(diss);
double p=(disr[i]+disr[j]+diss)/2.0;
double aera=sqrt(p*(p-disr[i])*(p-disr[j])*(p-diss));
double hhh=aera*2.0/diss;
//情况有4种:1段直线,1段弧线,1段弧线和1段直线,1段弧线和2段直线
if(hhh>=r||disr[i]*disr[i]+diss*diss<=disr[j]*disr[j]||disr[j]*disr[j]+diss*diss<=disr[i]*disr[i]){
iui+=diss;continue;
}
//上边是1段直线的情况
//下边直接把后三种情况合一
double cosc=(disr[i]*disr[i]+disr[j]*disr[j]-diss*diss)/(2*disr[i]*disr[j]);
double tht=acos(cosc);
double k1=sqrt(disr[i]*disr[i]-1.0*r*r),k2=sqrt(disr[j]*disr[j]-1.0*r*r);
double tht1= acos( (disr[i]*disr[i]+1.0*r*r-k1*k1)/(2.0*disr[i]*r) );
double tht2= acos( (disr[j]*disr[j]+1.0*r*r-k2*k2)/(2.0*disr[j]*r) );
double tht3=tht-tht1-tht2;double k3=r*tht3;
iui+=k1+k2+k3;
}
printf("%.15f\n",iui);
}
return 0;
}