202009-4 星际旅行
/*注意事项 1.c语言中三角函数的用法sin(),asin(),cos(),acos() 2.注意分类讨论的情况,分两点之间的直线是在圆内还是圆外进行讨论 3.注意大数组直接打表,求得的部分结果存好 4. 请以“整数部分、小数点、小数部分”的格式输出实数,并保留不少于 12 位小数结果。采用其他格式(如科学记数法)输出可能无法得分 5.4的含义是用 printf("%.13lf\n", ans)这种形式,并不需要单独设计相应的数据结构,小数点位数只要超过12位即可 */ #include <bits/stdc++.h> using namespace std; int n, m; // n维欧几里得空间宇宙,m个星际旅行坐标 int r; // 黑洞半径为r int O[105]; // 超球体黑洞的中心O的每一维坐标 int P[2005][105]; // 每个目标点的n维坐标 double dis[2005][2005]; // 两点间的旅行距离 double ans; long dirdis2[2005][2005]; // 两点间直线距离的平方值 long PO2[2005]; // 每个目标点到黑洞中心距离的平方值 /**计算两点间直线距离的平方值(整型)**/ long caldirdis(int x, int y){ long ans = 0; for(int j=0;j<n;++j) ans += (P[x][j]-P[y][j])*(P[x][j]-P[y][j]); return ans; } /**判断连线是否在黑洞外**/ bool isOut(int x, int y) { // 海伦-秦九韶公式计算三角形面积 double a = sqrt(PO2[x]); double b = sqrt(PO2[y]); double c = sqrt(dirdis2[x][y]); double p = (a + b + c) / 2; double S = sqrt(p*(p-a)*(p-b)*(p-c)); // 面积公式计算O点到直线xy的距离h double h = 2 * S / c; if(h>=r) return 1; else if(c*c+a*a<=b*b) return 1; // 特殊情况!!!钝角三角形 else if(c*c+b*b<=a*a) return 1; // 特殊情况!!!钝角三角形 else return 0; } /**计算x,y两点与O点形成夹角的弧度值**/ double caltheta(int x, int y){ double a = sqrt(PO2[x]); double b = sqrt(PO2[y]); double c = sqrt(dirdis2[x][y]); return acos((a*a+b*b-c*c) / (2*a*b)); } /**两点间带曲线路程计算**/ double calcirdis(int x, int y) { double a2 = PO2[x]; double b2 = PO2[y]; /**曲线路程 = 黑洞表面曲线部分 + x点到切点的距离 + y点到切点的距离**/ double part1 = caltheta(x, y)*r - acos(sqrt(r*r/a2))*r - acos(sqrt(r*r/b2))*r; double part2 = sqrt(a2-r*r); double part3 = sqrt(b2-r*r); return part1 + part2 + part3; } /**求出两点之间的旅行距离**/ void caldis(int x, int y){ dirdis2[x][y] = caldirdis(x, y); // 先计算两点间直线距离的平方值 dirdis2[y][x] = dirdis2[x][y]; // 判断两点间连线是否在黑洞之外 if(isOut(x, y)){ // 黑洞之外 dis[x][y] = sqrt(dirdis2[x][y]); // 路程为dirdis2开平方 dis[y][x] = dis[x][y]; } else{ // 黑洞之内 dis[x][y] = calcirdis(x, y); // 调用曲线路程函数计算 dis[y][x] = dis[x][y]; } } int main() { cin >> n >> m; cin >> r; for(int j=0;j<n;++j) cin >> O[j]; for(int i=0;i<m;++i){ // 每个目标点 PO2[i] = 0; for(int j=0;j<n;++j){ // 每一维坐标 cin >> P[i][j]; PO2[i] += (P[i][j]-O[j])*(P[i][j]-O[j]); // 记录该点到黑洞中心距离的平方值(整型) } } /**求出两点之间的旅行距离**/ for(int i=0;i<m;++i) for(int j=i+1;j<m;++j) caldis(i, j); for(int i=0;i<m;++i){ ans = 0; for(int j=0;j<m;++j) ans = ans + dis[i][j]; printf("%.13lf\n", ans); // %m.nlf->m:输出数据总的长度,n:小数位数,%lf为double型双精度 } return 0; }