#include <iostream>
#include <vector>
#include <cstring>
#include <math.h>
using namespace std;
const int N =2100;
int n,m,r;
// vector<double> yuanxin;
// vector<double> point;
double yuanxin[N];
double point[N][N];
double ans[N][N];
double A[N],B[N];
double nums[N];
double tp(double xx)
{
return xx*xx;
}
int main()
{
cin >> n >> m;
cin >> r;
for(int i=0;i < n;i++)
{
cin >> yuanxin[i];
// yuanxin.pusu_back(num);
}
for(int i=0;i < m;i++)
{
for(int j=0;j < n;j++) cin >> point[i][j];
}
// 对于每个点,判断经不经过圆
for(int i=0;i < m;i++)
{
for(int k=i+1;k < m;k++) // 与其他的点
{
memcpy(A,point[i],sizeof(point[i]));
memcpy(B,point[k],sizeof(point[k]));
// A = point[i],B = point[k]; // 这种赋值方法会报错
// AB这条直线的方程,!!直线方程太难求了,要通过面积来计算o(╥﹏╥)o
double dab = 0,dao = 0,dbo = 0;
for(int j=0;j < n;j++)
{
dab += tp(A[j] - B[j]);
dao += tp(A[j] - yuanxin[j]);
dbo += tp(B[j] - yuanxin[j]);
}
dab = sqrt(dab),dao = sqrt(dao),dbo = sqrt(dbo);
double p = (dab + dao + dbo)/2;
double S = sqrt(p*(p-dab)*(p-dao)*(p-dbo));
double h = S / dab * 2;
double a1 = (tp(dab)+tp(dao)-tp(dbo))/(2*dab*dao);
double b1 = (tp(dab)+tp(dbo)-tp(dao))/(2*dab*dbo);
if(h >= r || ((h < r) && (a1 < 0 || b1 < 0))) // 相切和相离 || 另一种相离 // 改了a1 < 0 && b1 < 0 之后超时
{
ans[i][k] = dab;
ans[k][i] = dab;
}
else // 有三段要计算
{
double l1 = sqrt(tp(dao) - tp(r));
double l2 = sqrt(tp(dbo) - tp(r));
double arch = acos((tp(dbo)+tp(dao)-tp(dab))/(2*dbo*dao))-acos((tp(r)+tp(dao)-tp(l1))/(2*r*dao)) - acos((tp(r)+tp(dbo)-tp(l2))/(2*r*dbo));
double l3 = arch*r; // 180.0/3.1416*这是转角度,不需要转角度
// cout << arch << endl;
ans[i][k] = l1 + l2 + l3;
ans[k][i] = ans[i][k];
}
}
}
for(int i=0;i < m;i++)
{
for(int j=0;j < m;j++)
{
// cout << ans[i][j] << " ";
nums[i] += ans[i][j];
}
// cout << endl;
}
for(int i=0;i < m;i++)
{
printf("%.13f\n",nums[i]);
// cout << nums[i] << endl;
}
return 0;
}
CSP 星际旅行 75分
最新推荐文章于 2024-09-25 10:36:42 发布
该程序主要解决计算几何中的问题,输入多个点的坐标和一个圆的半径,判断任意两点间连线是否经过圆,并计算出相应的距离。程序使用了向量和距离公式,通过判断点到圆心的距离和半径的关系来确定线段与圆的位置关系,最终输出所有点对之间的最短距离总和。
摘要由CSDN通过智能技术生成