• 【BZOJ1013】【JSOI2008】球形空间产生器sphere(高斯消元)


    1013: [JSOI2008]球形空间产生器sphere

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 1600  Solved: 860
    [Submit][Status]

    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的坐标为(a1, a2, …, an), (b1, b2, …, bn),则AB的距离定义为:dist = sqrt( (a1-b1)^2 + (a2-b2)^2 + … + (an-bn)^2 )

     

    Source

    分析:

    设球心坐标为(x1,x2,x3,...,xn),球的半径为R

    则可以根据N+1个点列出N+1个方程

    (a1-x1)^2+(a2-x2)^2+...+(an-xn)^2=R^2 ①

    (b1-x1)^2+(b2-x2)^2+...+(bn-xn)^2=R^2 ②

    (c1-x1)^2+(c2-x2)^2+...+(cn-xn)^2=R^2 ③

    ......

    然后把①-②得到2(a1-b1)x1+2(a2-b2)x2+...+2(an-bn)xn=a1^2-b1^2+a2^2-b2^2+...+an^2-bn^2

    同理②-③,③-④,...都能得到类似的式子

    发现N+1个方程变成了N个方程,且这N个方程左边都是一个确切的数,即N元一次方程

    然后就对N个方程高斯消元求解,注意精度即可

    code:

    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int maxn=10;
    const double eps=1e-8;
    double a[maxn+5][maxn+5],b[maxn+5][maxn+5];
    int n;
    int main()
    {
    	freopen("ce.in","r",stdin);
    	freopen("ce.out","w",stdout);
    	scanf("%d",&n);
    	for(int i=1;i<=n+1;++i)
    		for(int j=1;j<=n;++j)
    			scanf("%lf",&b[i][j]);
    	for(int i=1;i<=n;++i)
    	{
    		double s=0.0;
    		for(int j=1;j<=n;++j) a[i][j]=2.0*(b[i][j]-b[i+1][j]),s+=b[i][j]*b[i][j]-b[i+1][j]*b[i+1][j];
    		a[i][n+1]=s;
    	}
    	for(int i=1;i<=n;++i)
    	{
    		if(a[i][i]==0)
    		{
    			int j;
    			for(j=i+1;j<=n;++j)	if(fabs(a[j][i]-0.0)<=eps) break;
    			for(int k=1;k<=n+1;++k) swap(a[i][k],a[j][k]);
    		}
    		for(int j=1;j<=n+1;++j) if(i!=j)a[i][j]/=a[i][i];a[i][i]=1.0;
    		for(int j=1;j<=n;++j)
    			if(j!=i) 
    			{
    				for(int k=1;k<=n+1;++k) if(k!=i) a[j][k]-=a[i][k]*a[j][i]/a[i][i];a[j][i]=0.0;
    			}
    	}
    	for(int i=1;i<n;++i) printf("%.3lf ",a[i][n+1]);printf("%.3lf",a[n][n+1]);
    	return 0;
    }
    
  • 相关阅读:
    Spring简介和基础
    el表达式
    Spring MVC 文件上传下载
    el表达式的function标签
    JSTL核心标签库使用
    基于注解的SpringMVC
    new一个Object对象占用多少内存?
    leetcode-第k个排列(Java和c++版)
    使用maven构建web项目(简易版)
    leetcode-电话号码的字母组合
  • 原文地址:https://www.cnblogs.com/wmrv587/p/3500195.html
Copyright © 2020-2023  润新知