bzoj 1013: [JSOI2008]球形空间产生器sphere【高斯消元】

n+1个坐标可以列出n个方程,以二维为例,设圆心为(x,y),给出三个点分别是(a1,b1),(a2,b2),(a3,b3)
因为圆上各点到圆心的距离相同,于是可以列出距离方程

\[(a1-x)^2+(b1-y)^2=(a2-x)^2+(b2-y)^2 \]

\[(a1-x)^2+(b1-y)^2=(a3-x)^2+(b3-y)^2 \]

然后化简

\[-2(a2-a1)x-2(b2-b1)y=a1^2-a2^2+b1^2-b2^2 \]

\[-2(a3-a1)x-2(b3-b1)y=a1^2-a3^2+b1^2-b3^2; \]

然后就可以用高斯消元了

#include<iostream>
#include<cstdio>
using namespace std;
const int N=25;
int n;
double f[N],a[N][N],p;
void gaosi()
{
	for(int i=1;i<=n;i++)
	{
		int nw=i;
		for(int j=i+1;j<=n;j++)
			if(a[j][i]>a[nw][i])
				nw=j;
		for(int j=i;j<=n+1;j++)
			swap(a[nw][j],a[i][j]);
		for(int j=i+1;j<=n+1;j++)
			a[i][j]/=a[i][i];
		a[i][i]=1;
		for(int j=i+1;j<=n;j++)
		{
			for(int k=i+1;k<=n+1;k++)
				a[j][k]-=a[j][i]*a[i][k];
			a[j][i]=0;
		}
	}
	for(int i=n;i>=1;i--)
		for(int j=i+1;j<=n;j++)
		{
			a[i][n+1]-=a[i][j]*a[j][n+1];
			a[i][j]=0;
		}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%lf",&f[i]);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
		{
			scanf("%lf",&p);
			a[i][j]=2*(p-f[j]);
			a[i][n+1]+=p*p-f[j]*f[j];
		}
	gaosi();
	for(int i=1;i<=n;i++)
		printf("%.3lf ",a[i][n+1]);
	return 0;
}
posted @ 2018-06-30 14:17  lokiii  阅读(155)  评论(0编辑  收藏  举报