P4035
[JSOI2008]球形空间产生器
高斯消元。
简单理解就是将线性方程组的系数化成矩阵,再与右侧常数项共同构成一个增广矩阵。
然后就是机械消元,通过一个方程乘上某个非零系数把其余方程的此项全部化 0,然后看下一项再重复执行次操作。
这题不存在主元和自由元,所以解出来就完事了。
这题所谓圆心的含义其实就是所有点到该点的距离相同。
所以就会有方程(组):
其中
然后这里我们尝试把这
那么相邻的两个方程作差,我们就可以得到含有
这里
然后我们就转化成下面的增广矩阵:
然后消元就完事了。
时间复杂度
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#define ll long long
using namespace std;
const ll N=20;
const double acc=1e-8;
ll n;
double a[N+5][N+5],b[N+5],c[N+5][N+5];
int main() {
scanf("%lld",&n);
for(ll i=1;i<=n+1;i++) {
for(ll j=1;j<=n;j++) {
scanf("%lf",&a[i][j]);
}
}
for(ll i=1;i<=n;i++) {
for(ll 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];
}
}
for(ll i=1;i<=n;i++) {
for(ll j=i;j<=n;j++) {
if(fabs(c[j][i])>acc) {
for(ll k=1;k<=n;k++) swap(c[i][k],c[j][k]);
swap(b[i],b[j]);
}
}
for(ll j=1;j<=n;j++) {
if(i==j) continue;
double rate=c[j][i]/c[i][i];
for(ll k=i;k<=n;k++) c[j][k]-=c[i][k]*rate;
b[j]-=b[i]*rate;
}
}
for(ll i=1;i<=n;i++) printf("%.3f ",b[i]/c[i][i]);
return 0;
}