题目描述
有一个球形空间产生器能够在n维空间中产生一个坚硬的球体。
现在,你被困在了这个n维球体中,你只知道球面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁这个球形空间产生器。
题解
题目大意:求在n维空间中n+1个点,求解一个点的坐标使得这个点到其他每一个点的距离都相等。
这道题的难点在于数学推导,推到完以后就直接套高斯消元模板即可。
若i∈[1,n+1]i∈[1,n+1]i∈[1,n+1],则每一个点到球心的距离CCC可以表示为,ppp为球心坐标:C=∑j=1n(ai,j−pj)2C=\sum_{j=1}^{n} (a_{i,j}-p_j)^2C=j=1∑n(ai,j−pj)2
显然对于每一份i来说,这一个CCC都是不变的。这是含有n+1n+1n+1个方程的一个二次方程组,十分难解;我们应该对其进行化简。
我们对这n+1n+1n+1个方程相减,则有:∑j=1n(ai,j−pj)2−(ai+1,j−pj)2=0,i∈[1,n]\sum_{j=1}^{n} (a_{i,j}-p_j)^2-(a_{i+1,j}-p_j)^2=0,i∈[1,n]j=1∑n(ai,j−pj)2−(ai+1,j−pj)2=0,i∈[1,n]
再大力展开,即可得到:
∑j=1npj∗2(ai−ai+1)=∑j=1nai−1,j2−ai,j2,i∈[1,n]\sum_{j=1}^{n}p_j*2(a_i-a_{i+1})=\sum_{j=1}^{n}a_{i-1,j}^2-a_{i,j}^2,i∈[1,n]j=1∑npj∗2(ai−ai+1)=j=1∑nai−1,j2−ai,j2,i∈[1,n]
这样我们就化简为了一个高斯消元的形式:
对于第iii行来说,有jjj个未知数.每一行j个未知数的和为定值。
若i,j∈[1,n],i,j∈[1,n],i,j∈[1,n],那个第iii行第jjj列所对应的未知数就是pj,p_j,pj,系数是2∗(ai−ai−1)2*(a_i-a_{i-1})2∗(ai−ai−1).
∑j=1nai−1,j2−ai,j2,i∈[1,n]\sum_{j=1}^{n}a_{i-1,j}^2-a_{i,j}^2,i∈[1,n]∑j=1nai−1,j2−ai,j2,i∈[1,n]则是方程之积。
然后直接套高斯消元的模板即可。
#include <bits/stdc++.h>
using namespace std;
int n;
double b[100];
double a[100][100];
double c[100][100];
int main(void)
{
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
cin>>n;
for (int i=1;i<=n+1;++i)
for (int j=1;j<=n;++j)
cin>>a[i][j];
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j)
{
c[i][j] = 2*(a[i][j]-a[i+1][j]);
b[i] += a[i][j]*a[i][j]-a[i+1][j]*a[i+1][j];
}
double eps = 1e-8;
for (int i=1;i<=n;++i)
{
for (int j=i;j<=n;++j)
if (fabs(c[j][i])>eps)
{
for (int k=1;k<=n;++k) swap(c[i][k],c[j][k]);
swap(b[i],b[j]);
break;
}
//交换第i行和第r行
for (int j=1;j<=n;++j)
{
if (i == j) continue;
double rate = c[j][i]/c[i][i];
for (int k=i;k<=n;++k)
c[j][k] -= c[i][k]*rate;
b[j] -= b[i]*rate;
}
}
for (int i=1;i<n;++i) printf("%.3lf ",b[i]/c[i][i]);
printf("%.3lf\n",b[n]/c[n][n]);
return 0;
}