[bzoj1013](JSOI2008)球形空间产生器sphere(高斯消元)

Description

有一个球形空间产生器能够在n维空间中产生一个坚硬的球体。现在,你被困在了这个n维球体中,你只知道球面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁这个球形空间产生器。

Input

第一行是一个整数,n。接下来的n+1行,每行有n个实数,表示球面上一点的n维坐标。每一个实数精确到小数点后6位,且其绝对值都不超过20000。

Output

有且只有一行,依次给出球心的n维坐标(n个实数),两个实数之间用一个空格隔开。每个实数精确到小数点后3位。数据保证有解。你的答案必须和标准输出一模一样才能够得分。

Sample Input

2
0.0 0.0
-1.0 1.0
1.0 0.0

Sample Output

0.500 1.500

HINT

数据规模:

对于40%的数据,1<=n<=3

对于100%的数据,1<=n<=10

提示:给出两个定义:

1、 球心:到球面上任意一点距离都相等的点。

2、 距离:设两个n为空间上的点A, B的坐标为$(a_1, a_2, …, a_n), (b_1, b_2, …, b_n)$,则AB的距离定义为:$$dist = \sqrt{ (a_1-b_1)^2 + (a_2-b_2)^2 + … + (a_n-b_n)^2 }$$

分析

     设球心坐标为$(x_1, x_2, ... , x_n)$,根据定义可以列出方程组:

$$ \forall i,j \in [1,n+1]: \sum_{k=1}^N (x_k - a_{ik})^2 = \sum_{k=1}^N (x_k - a_{jk})^2$$.

     展开后移项相减,得到

$$\sum_{k=1}^N 2(a_{ik} - a_{jk})x_k = a_{ik}^2 - a_{jk}^2 $$

    由于变量有N个,我们只需选取其中N组线性无关(或可以使所有无向边(i,j)构成一棵树)的(i,j)方程来求解即可。

    题目本身不难,可是为学校OJ造测试数据这种事简直醉人……我的做法是先随机出一个N维向量作为答案,再随机出半径R,接着循环N+1次,每次随机一个N-1维向量,求出这条直线与球的交点……最终还要运行一遍本题的高斯消元判断这些点是否线性相关……

    好吧其实真正的问题是我太水了……敲错了datamaker调试了好久= =

 

技术分享
 1 /**************************************************************
 2     Problem: 1013
 3     User: AsmDef
 4     Language: C++
 5     Result: Accepted
 6     Time:0 ms
 7     Memory:1272 kb
 8 ****************************************************************/
 9  
10 //Asm_Def
11 #include <iostream>
12 #include <cctype>
13 #include <cstdio>
14 #include <vector>
15 #include <algorithm>
16 #include <cmath>
17 #include <queue>
18 using namespace std;
19 template<typename T>inline void getd(T &x){
20     char c = getchar();
21     bool minus = 0;
22     while(!isdigit(c) && c != -)c = getchar();
23     if(c == -)minus = 1, c = getchar();
24     x = c - 0;
25     while(isdigit(c = getchar()))x = x * 10 + c - 0;
26     if(minus)x = -x;
27 }
28 /*======================================================*/
29 const double eps = 1e-12;
30 double *Eq[11], Ans[11];
31 int N;
32 inline void init(){
33     double a, P[11][12];
34     getd(N);int i, j;
35     for(j = 0;j < N;++j)scanf("%lf", *P + j);
36     for(i = 1;i <= N;++i){
37         for(j = 0;j < N;++j)
38             scanf("%lf", P[i] + j);
39         P[i-1][N] = 0;
40         for(j = 0;j < N;++j){
41             a = P[i-1][j] + P[i][j];
42             P[i-1][j] = P[i][j] - P[i-1][j];
43             P[i-1][N] += a * P[i-1][j] / 2.0;
44         }
45         Eq[i-1] = P[i-1];
46     }
47 }
48 inline void solve(){
49     int i, j, k;
50     double frac;
51     for(i = 0;i < N;++i){
52         for(j = i+1;j < N;++j)
53             if(fabs(Eq[i][i]) < fabs(Eq[j][i]))swap(Eq[i], Eq[j]);
54          
55         if(fabs(Eq[i][i]) < eps){
56             cout << "No Answer" << endl;
57             exit(1);
58         }
59         for(j = i+1;j < N;++j){
60             if(fabs(frac = Eq[j][i] / Eq[i][i]) < eps)continue;
61             Eq[j][i] = 0;
62             for(k = i+1;k <= N;++k)
63                 Eq[j][k] -= frac * Eq[i][k];
64         }
65     }
66     for(i = N-1;i >= 0;--i){
67         Ans[i] = Eq[i][N] / Eq[i][i];
68         for(j = 0;j < i;++j)
69             Eq[j][N] -= Eq[j][i] * Ans[i];
70     }
71     for(i = 0;i < N;++i)
72         printf("%.3lf%c", Ans[i], i == N-1 ? \n :  );
73 }
74 int main(){
75     #if defined DEBUG
76     //freopen("test", "r", stdin);
77     #else
78     //freopen("bzoj_1013.in", "r", stdin);
79     //freopen("bzoj_1013.out", "w", stdout);
80     #endif
81     init();
82     solve();
83      
84     #if defined DEBUG
85     //cout << endl << (double)clock()/CLOCKS_PER_SEC << endl;
86     #endif
87     return 0;
88 }
高斯消元

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。