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