• Luogu4035/BZOJ1013 [JSOI2008]球形空间产生器


    题目传送门

    算法分析

    不妨设未知数\(d\)表示每一个点到球心的距离,设未知数\(b_1,b_2,\cdots,b_n\)表示球心的坐标。

    我们不难得到\(n+1\)个方程:

    \[d^2=\sum_{i=1}^n{(a_i-b_i)^2} \]

    发现出现二次项了,这里显然不可以用换元法把二次项换成一次项。

    我们把这个式子展开:

    \[d^2=\sum_{i=1}^n{a_i^2}+\sum_{i=1}^n{b_i^2}+2\times \sum_{i=1}^n{a_ib_i} \]

    未知数写到同一侧:

    \[-2\times \sum_{i=1}^n{a_ib_i}-\sum_{i=1}^n{b_i^2}+d^2=\sum_{i=1}^n{a_i^2} \]

    这时我们发现,对于每一个方程,所有的二次项系数都是相同的,因此我们考虑邻项相消,得出如下的\(n\)个方程:

    \[-2\times \sum_{i=1}^n{(a_i-a_{i-1})b_i}=\sum_{i=1}^n{a_i^2-a_{i-1}^2} \]

    这符合高斯消元的条件,直接做即可。

    代码实现

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 105
    int n;
    double a[maxn][maxn],b[maxn][maxn],x[maxn][maxn];
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n+1;i++){
    		for(int j=1;j<=n;j++){
    			scanf("%lf",&x[i][j]);
    		}
    	}
    	for(int i=1;i<=n+1;i++){
    		for(int j=1;j<=n;j++){
    			b[i][j]=(-2)*x[i][j];
    		}
    		for(int j=1;j<=n;j++)b[i][n+1]-=(x[i][j]*x[i][j]);
    	}
    	for(int i=1;i<=n+1;i++){
    		for(int j=2;j<=n+1;j++){
    			a[i][j]=b[i][j]-b[i-1][j];
    		}
    	}
    	for(int i=1;i<=n;i++){
    		int p=0;
    		for(int j=i;j<=n;j++){if(a[j][i]){p=j;break;}}
    		if(!p)continue;
    		for(int j=1;j<=n+1;j++)swap(a[i][j],a[p][j]);
    		double k=a[i][i];
    		for(int j=1;j<=n+1;j++)a[i][j]/=k;
    		for(int j=1;j<=n;j++){
    			if(i==j)continue;
    			double kk=a[j][i];
    			for(int l=1;l<=n+1;l++)a[j][l]-=kk*a[i][l];
    		}
    	}
    	for(int i=1;i<=n;i++)printf("%.3lf ",a[i][n+1]);
    	return 0;
    }
    
    
  • 相关阅读:
    NYoj 素数环(深搜入门)
    深搜和广搜
    hdu 3449 (有依赖的01背包)
    hdu 1712 (分组背包入门)
    sql数据库常用语句总结
    常用工具和API的网站收集
    23种设计模式
    sql 联合查询并更新
    sql 去除重复记录
    读<你必须知道的.NET>IL指令笔记
  • 原文地址:https://www.cnblogs.com/ZigZagKmp/p/11491053.html
Copyright © 2020-2023  润新知