Problem
【JSOI2008】球形空间产生器
TimeLimit:1Sec
MemoryLimit:162MB
Description
有一个球形空间产生器能够在n维空间中产生一个坚硬的球体。
现在,你被困在了这个n维球体中,你只知道球面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁这个球形空间产生器。
第一行是一个整数n(1≤n≤10)。
接下来的n+1行,每行有n个实数,表示球面上一点的n维坐标。
每一个实数精确到小数点后6位,且其绝对值都不超过20000。
Output
有且只有一行,依次给出球心的n维坐标(n个实数),两个实数之间用一个空格隔开。
每个实数精确到小数点后3位,数据保证有解,你的答案必须和标准输出一模一样才能够得分。
1 2 3 4
| 2 0.0 0.0 -1.0 1.0 1.0 0.0
|
Sample Output
HINT
给出两个定义:
- 球心:到球面上任意一点距离都相等的点。
- 距离:设两个n维空间上的点A,B的坐标为(a1,a2,⋯,an),(b1,b2,⋯,bn),则AB的距离定义为:dist=(a1−b1)2+(a2−b2)2+⋯+(an−bn)2
标签:高斯消元
Solution
高消裸题。
将第n+1个点单独分出来,将其与前n个点分别联立形成n个方程,高消即可求得球心坐标。
设球心为(x1,x2,⋯,xn),第n+1个点为(t1,t2,⋯,tn)。对于前n个点中的一个点A,设A坐标为(a1,a2,⋯,an)。那么一定有
(a1−x1)2+(a2−x2)2+⋯+(an−xn)2=(t1−x1)2+(t2−x2)2+⋯+(tn−xn)2
展开得
i=1∑nai2+i=1∑nxi2−2i=1∑naixi=i=1∑nti2+i=1∑nxi2−2i=1∑ntixi
移项化简
2i=1∑n(ai−ti)xi=i=1∑nai2−i=1∑nti2
直接高斯消元解方程组,时间复杂度O(n3)。
★注意行末不要输出空格
Code
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
| #include <bits/stdc++.h> #define EPS 1e-8 using namespace std; typedef double dnt; int n; dnt p[15][15], f[15][15]; dnt sqr(dnt x) {return x*x;} bool Gauss() { for (int i = 1, t; i <= n; i++) { for (t = i; t <= n; t++) if (fabs(f[t][i]) >= EPS) break; if (t > n) return false; swap(f[i], f[t]); for (int j = 1; j <= n; j++) if (i^j) { dnt div = f[j][i]/f[i][i]; for (int k = 1; k <= n+1; k++) f[j][k] -= f[i][k]*div; } } for (int i = 1; i <= n; i++) f[i][n+1] /= f[i][i]; return true; } int main() { scanf("%d", &n); for (int i = 1; i <= n+1; i++) for (int j = 1; j <= n; j++) scanf("%lf", p[i]+j); for (int i = 1, j = n+1; i <= n; i++) for (int k = 1; k <= n; k++) f[i][k] = p[i][k]-p[j][k], f[i][n+1] += (sqr(p[i][k])-sqr(p[j][k]))/2; Gauss(); for (int i = 1; i <= n; i++) if (i^n) printf("%.3lf ", f[i][n+1]); else printf("%.3lf", f[i][n+1]); return 0; }
|