Luogu P4035 [JSOI2008]球形空间产生器

题目描述

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

输入格式

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

输出格式

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

题目链接

思路

根据题意得

\[(x_{1}-a_{1})^2+(x_{2}-a_{2})^2+.......+(x_{n}-a_{n})^2=r^2 \]

可化为

$ 2a_{1}x_{1}+2a_{2}x_{2}+......+2a_{n}x_{n}-r2-x_{1}-x_{2}{2}-......-x_{n}=a_{1}{2}+.......a_{n} $

设 $ t=-r2-x_{1}-x_{2}{2}-......-x_{n} $

所以得到

$ 2a_{1}x_{1}+2a_{2}x_{2}+......+2a_{n}x_{n}+t=a_{1}{2}+.......a_{n} $

因此可以得到一个 \(n+1\)元方程组

利用高斯消元求解,别忘了总数是 \(n+1\) 而不是 \(n\) (调了半小时的祸根)

(\(\mathrm{LaTeX}\)好难打呀)

code

#include<bits/stdc++.h>
using namespace std;
const int MAXN=20;
double a[MAXN][MAXN],num;
int n;

void debug()
{
	puts("---------------------------------");
	for(int i=1;i<=n+1;++i){
		for(int j=1;j<=n+2;++j){
			cout<<fixed<<setprecision(2)<<a[i][j]<<"	";
		}
		putchar('\n');
	}
}

void gauss()
{
	for(int i=1;i<=n+1;i++){
//		debug();
		int now=i;
		while(a[now][i]==0&&now<=n+1){
			now++;
		}
		if(now==n+2){
			puts("???");
			exit(233);
		}
		for(int j=1;j<=n+2;j++){
			swap(a[i][j],a[now][j]);
		}
		double k=a[i][i];
		for(int j=1;j<=n+2;j++){
			a[i][j]/=k;
		}
		for(int j=1;j<=n+1;j++){
			if(j!=i){
				double kkk=a[j][i];
				for(int k=1;k<=n+2;k++){
					a[j][k]-=kkk*a[i][k];
				}
			}
		}
		
	}
}

int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	cin>>n;
	for(int i=1;i<=n+1;++i){
		for(int j=1;j<=n;j++){
			cin>>num;
			a[i][j]=2*num,a[i][n+2]+=num*num;
		}
		a[i][n+1]=1;
	}
	gauss();
	for(int i=1;i<=n;++i){
		cout<<fixed<<setprecision(3)<<a[i][n+2]<<' ';
	}
	return 0;
}

参考博客#

posted @ 2019-09-15 10:55  zhu_chen  阅读(125)  评论(0编辑  收藏  举报