[BZOJ1013][JSOI2008]球形空间产生器sphere
[BZOJ1013][JSOI2008]球形空间产生器sphere
试题描述
有一个球形空间产生器能够在n维空间中产生一个坚硬的球体。现在,你被困在了这个n维球体中,你只知道球
面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁这个球形空间产生器。
面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁这个球形空间产生器。
输入
第一行是一个整数n(1<=N=10)。接下来的n+1行,每行有n个实数,表示球面上一点的n维坐标。每一个实数精确到小数点
后6位,且其绝对值都不超过20000。
输出
有且只有一行,依次给出球心的n维坐标(n个实数),两个实数之间用一个空格隔开。每个实数精确到小数点
后3位。数据保证有解。你的答案必须和标准输出一模一样才能够得分。
输入示例
2 0.0 0.0 -1.0 1.0 1.0 0.0
输出示例
0.500 1.500
数据规模及约定
见“输入”
题解
因为是个球,所以第 i 号点和第 i+1 号点到球心的距离相等(1 ≤ i ≤ n),推一波式子发现未知数平方项被消了,所以就是个裸的高斯消元。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <cmath>
using namespace std;
int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}
#define maxn 20
#define eps 1e-6
int n;
double x[maxn][maxn], A[maxn][maxn];
double sqr(double x) { return x * x; }
int main() {
n = read();
for(int i = 1; i <= n + 1; i++)
for(int j = 1; j <= n; j++)
scanf("%lf", &x[i][j]);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
A[i][j] = 2.0 * (x[i][j] - x[i+1][j]), A[i][n+1] += sqr(x[i][j]) - sqr(x[i+1][j]);
/*for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) printf("%.3lf ", A[i][j]);
printf("| %.3lf\n", A[i][n+1]);
}*/
for(int i = 1; i <= n; i++) {
int x; bool has = 0;
for(x = i; x <= n; x++) if(fabs(A[x][i]) > eps) {
has = 1; break;
}
if(!has) continue;
if(x != i) for(int j = 1; j <= n + 1; j++) swap(A[x][j], A[i][j]);
double t = A[i][i];
for(x = 1; x <= n; x++) if(x != i && fabs(A[x][i]) > eps) {
double r = -t / A[x][i];
for(int j = 1; j <= n + 1; j++) A[x][j] = A[x][j] * r + A[i][j];
}
}
/*for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) printf("%.3lf ", A[i][j]);
printf("| %.3lf\n", A[i][n+1]);
}*/
for(int i = 1; i < n; i++) printf("%.3lf ", A[i][n+1] / A[i][i]);
printf("%.3lf\n", A[n][n+1] / A[n][n]);
return 0;
}

浙公网安备 33010602011771号