[JSOI2008]球形空间产生器

洛咕

题意:有一个n维球体,你知道球面上n+1个点的坐标,你需要确定这个n维球体的球心坐标.

分析:对于一个球,球面上任意一点到球心的距离都是相等的,我们可以根据这条性质,列出n+1个方程。但方程右边全都是半径,而半径我们正好又不知道,所以可以通过相邻两个方程相减从而消去半径,同时也构造出了我们熟悉的n个n元一次方程。直接高斯消元(my学习笔记)

#include<bits/stdc++.h>
using namespace std;
double a[20][20],b[20][20];
int main(){
    int n;cin>>n;
    for(int i=1;i<=n+1;i++)
    	for(int j=1;j<=n;j++)
        	scanf("%lf",&a[i][j]);
//读入n+1个点的n维坐标
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            b[i][j]=2*(a[i][j]-a[i+1][j]);
//因为点的坐标^2-球心坐标^2=半径^2,化简一下就会有个乘2
            b[i][n+1]+=(a[i][j]*a[i][j]-a[i+1][j]*a[i+1][j]);
        }		
//构造出n个n元一次方程
    for(int i=1;i<=n;i++){//高斯消元的模板
			int now=i;
			for(int j=i+1;j<=n;j++)
				if(fabs(b[now][i])<fabs(b[j][i]))now=j;
			if(now!=i){
				for(int j=i;j<=n+1;j++)
					swap(b[i][j],b[now][j]);
			}
			for(int j=i+1;j<=n+1;j++)
				b[i][j]/=b[i][i];
			b[i][i]=1;
			for(int j=i+1;j<=n;j++){
				for(int k=i+1;k<=n+1;k++)
					b[j][k]-=b[j][i]*b[i][k];
				b[j][i]=0;
			}	 
	}	
	for(int i=n;i>=1;i--){
		for(int j=i+1;j<=n;j++){
			b[i][n+1]-=b[i][j]*b[j][n+1];
			b[i][j]=0;
		}
	}
	for(int i=1;i<=n;i++)
		printf("%.3lf ",b[i][n+1]);
   return 0;
} 
原文地址:https://www.cnblogs.com/PPXppx/p/10588509.html