BZOJ 1013: [JSOI2008]球形空间产生器sphere (解方程)
1013: [JSOI2008]球形空间产生器sphere
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 7277 Solved: 3931
[Submit][Status][Discuss]
Description
有一个球形空间产生器能够在n维空间中产生一个坚硬的球体。现在,你被困在了这个n维球体中,你只知道球
面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁这个球形空间产生器。
Input
第一行是一个整数n(1<=N=10)。接下来的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
0.0 0.0
-1.0 1.0
1.0 0.0
Sample Output
0.500 1.500
HINT
提示:给出两个定义:1、 球心:到球面上任意一点距离都相等的点。2、 距离:设两个n为空间上的点A, B
的坐标为(a1, a2, …, an), (b1, b2, …, bn),则AB的距离定义为:dist = sqrt( (a1-b1)^2 + (a2-b2)^2 +
… + (an-bn)^2 )
无脑解一个n+1维方程即可。
#include<iostream> #include<cstring> #include<string> #include<vector> #include <algorithm> #include <stack> #include <queue> #include <cmath> using namespace std; const int N=1005; #define inf 0x3f3f3f3f typedef pair<int,int> pi; typedef long long ll; int n; class Equal{ private: typedef unsigned int __index; double **data; double **vec; double *res; __index Sphere; void Swap(__index i,__index j){///交换ij两行位置 double *temp = data[i]; data[i] =data[j]; data[j] = temp; } void Add(__index i,__index j,double k){///j 行所有元素+=k倍i行 for(__index _ = 0 ; _ < Sphere+2 ; ++_){ data[j][_]+=data[i][_]*k; } } inline bool Zero(double K){ return fabs(K)<0.0000001; } public: explicit Equal(__index n):Sphere(n){ vec = new double*[Sphere+1]; data = new double*[Sphere+1]; res = new double[Sphere+1]; for(int i = 0 ; i <= Sphere ; ++i){ vec[i] = new double[Sphere]; data[i] = new double[Sphere+2]; } } void init(){ for(__index i = 0 ; i <= Sphere ; ++i){ for(__index j = 0 ; j < Sphere ; ++j){ cin>>vec[i][j];///第i个向量的第j个元素 } } double Sum; for(__index i = 0 ; i <= Sphere ; ++i){ Sum = 0; for(__index j = 0 ; j < Sphere ; ++j){ data[i][j] = 2*vec[i][j]; Sum+=vec[i][j]*vec[i][j]; } data[i][Sphere] = 1; data[i][Sphere+1] = Sum; } } void solve(){ __index cur = 0; for(__index i = 0 ; i <= Sphere ;++i){ while ( cur<= Sphere and Zero(data[i][cur])){ for(__index j = i+1 ; j <=Sphere ; ++j){ if(!Zero(data[j][cur])){ Swap(i,j); break; } } if(Zero(data[i][cur]))++cur; } if(cur<=Sphere){ for(__index j = i+1 ; j <= Sphere ; ++j){ if(!Zero(data[j][cur])){ Add(i,j,-data[j][cur]/data[i][cur]); } } } } for(__index j = Sphere ; j >= 0 ; --j){////只能解有解的方程.... double ans = data[j][Sphere+1]; for(__index i = j+1 ; i <= Sphere ; ++i){ ans-=res[i]*data[j][i]; } res[j] = ans/data[j][j]; if(j==0)break; } } void Show(){ for(__index i = 0 ; i < Sphere ; ++i){ printf("%.3f",res[i]); if(i!=Sphere-1){ printf(" "); }else printf("\n"); } } }; int main() { unsigned int n; cin>>n; Equal res(n); res.init(); res.solve(); res.Show(); }