「JSOI2008」球形空间产生器

纳尼?n维空间?什么鬼???

传送门

洛谷P4035

BZOJ1013

题解

根据题目的说明,设球心的坐标为$Oj(j \in [1,n])$,$n+1$个点的坐标为$X{ij}(i \in[1,n+1],j\in{1,n})$,$R$为半径,那么就有$n+1$个这样的式子:

将$R$消去,平方展开,移项后,可以得到$n$个这样的方程:

狠狠盯着方程几秒钟,然后你就会发现方程中只有$O_j$是未知数,其他都是常数,所以这$n​$个方程构成了一个n元非齐次线性方程组说人话叫做n元一次方程组)。

怎么解呢?

上高斯消元啊啊啊!!!

才发现什么矩阵行列式之类的东西都忘得差不多了,吓得我赶紧掏出了线性代数小紫书

那么 ,怎么用高斯消元法 解线性方程组呢?且听下回分解请左拐至…

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include<cstdio>
#include<algorithm>
using namespace std;
int n;double a[15][15],A[15][15];
double ABS(double x){return x<0?-x:x;}
inline void Gauss() //高斯消元解方程
{
for(int i=1;i<=n;i++)
{
int now=i;
for(int j=i+1;j<=n;j++)
if(ABS(A[j][i]>A[now][i]))
now=j;
if(now!=i)
for(int j=i;j<=n+1;j++)
swap(A[now][j],A[i][j]);
for(int k=i+1;k<=n;k++)
{
double t=A[k][i]/A[i][i];
for(int j=i;j<=n+1;j++) A[k][j]-=A[i][j]*t;
}
}
for(int i=n;i;i--)
{
for(int j=i+1;j<=n;j++)
A[i][n+1]-=A[j][n+1]*A[i][j];
A[i][n+1]/=A[i][i];
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n+1;i++)
for(int j=1;j<=n;j++)
scanf("%lf",&a[i][j]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
A[i][j]=2*(a[i+1][j]-a[i][j]);
A[i][n+1]+=a[i+1][j]*a[i+1][j]-a[i][j]*a[i][j];
}
}
//A数组是该n元非齐次线性方程组的增广矩阵
Gauss();
for(int i=1;i<=n;i++)
printf("%.3lf%c",A[i][n+1],i==n?'\n':' ');
return 0;
}