• BZOJ1013球形空间产生器sphere 高斯消元


    @[高斯消元]

    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
    

    Sample Output

    0.500 1.500
    

    HINT

    提示:给出两个定义:1、 球心:到球面上任意一点距离都相等的点。2、 距离:设两个n为空间上的点A, B的坐标为((a_1, a_2 .. a_n), (b_1, b_2 .. b_n)), 则AB的距离定义为:(dist = sqrt{(a_1 - b_1) ^ 2 + (a_2 - b_2) ^ 2 + .. + (a_n - b_n) ^ 2})

    Solution

    這題很尷尬的一點就是方程帶有二次項, 而且半徑也尚不能確定.
    然而又發現, 這題只有(n)個未知數, 但是給了(n + 1)個點的座標. 因此, 這一題可以通過作差的方式把二次项降到一次項. 具體來說, 就是:
    原式:

    [(a_1 - x_1) ^ 2 + (a_2 - x_2) ^ 2 + .. + (a_n - x_n) ^ 2 = r ^ 2 ]

    [(b_1 - x_1) ^ 2 + (b_2 - x_2) ^ 2 + .. + (b_n - x_n) ^ 2 = r ^ 2 ]

    作差後:

    [(a_1 - x_1) ^ 2 + (a_2 - x_2) ^ 2 + .. + (a_n - x_n) ^2 = (b_1 - x_1) ^ 2 + (b_2 - x_2) ^ 2 + .. + (b_n - x_n) ^ 2 ]

    [2 * (a_1 - b_1) * x_1 + (a_2 - b_2) * x_2 + .. + (a_n - b_n) * x_n = a_1 ^ 2 + a_2 ^ 2 + .. + a_n ^ 2 - b_1 ^ 2 - b_2 ^ 2 - .. - b_n ^ 2 ]

    因此(n - 1)個座標得到(n)個線性方程組, 可以用高斯消元發解決.
    至於關於高斯消元發的具體步驟, 直接看代碼就好了.

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N = 1 << 4;
    double f[N];
    double equa[N][N];
    
    inline double sqr(double x)
    {
    	return x * x;
    }
    
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("BZOJ1013.in", "r", stdin);
    	freopen("BZOJ1013.out", "w", stdout);
    	#endif
    	
    	int n;
    	scanf("%d", &n);
    	
    	for(int i = 0; i < n; i ++)
    		scanf("%lf", &f[i]);
    		
    	memset(equa, 0, sizeof(equa));
    	
    	for(int i = 0; i < n; i ++)
    		for(int j = 0; j < n; j ++)
    		{
    			double x;
    			scanf("%lf", &x);
    			equa[i][j] = 2 * (x - f[j]);
    			equa[i][n] += sqr(x) - sqr(f[j]);
    		}
    	
    	for(int i = 0; i < n; i ++)
    	{
    		double mx = - 1.0;
    		int ID;
    		
    		for(int j = i; j < n; j ++)
    			if(fabs(equa[j][i]) > mx)
    				mx = fabs(equa[j][i]), ID = j;
    				
    		swap(equa[ID], equa[i]);
    			
    		for(int j = 0; j < n; j ++)
    			if(i != j)
    				for(int k = n; ~ k; k --)
    					equa[j][k] -= equa[j][i] / equa[i][i] * equa[i][k];
    	}
    	
    	for(int i = 0; i < n - 1; i ++)
    		printf("%.3lf ", equa[i][n] / equa[i][i]);
    		
    	printf("%.3lf
    ", equa[n - 1][n] / equa[n - 1][n - 1]);
    } 
    
  • 相关阅读:
    委托的说明和举例
    用C#编写获取远程IP,MAC的方法
    200个Gmail邀请,要的请留下邮箱地址
    .NET中各种数据库连接大全
    .net中何有效的使用Cache
    55种网页常用小技巧(javascript) (转)
    一个WEB项目安装包,自动配置数据库,config文件和虚拟目录。。(转)
    windows xp sp2后所有更新
    C#反射实例(转)
    可扩展的应用程序:新增功能时无须重新编译
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/6418943.html
Copyright © 2020-2023  润新知