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;
}

 

posted @ 2021-04-04 21:51  zmachine  阅读(148)  评论(0编辑  收藏  举报