P4035 [JSOI2008]球形空間產生器
阿新 • • 發佈:2020-12-05
題目大意:給定球面上 \(n+1\) 個點的座標,求球心的座標?
總體思路:推柿子+高斯消元
已知 \(n\) 維空間上的兩個點座標為 \((a_1,a_2,a_3...a_n)\) 和 \((b_1,b_2,b_3...b_n)\),那麼他們的距離為:
\(dis=\sqrt{(a_1-b_1)^2+(a_2-b_2)^2+...+(a_n-b_n)^2}\)
那麼這就是圓心到圓上一點的距離了,也就是半徑,稱為 \(r\)。
\[\sqrt{(a_1-b_1)^2+(a_2-b_2)^2+...+(a_n-b_n)^2}=r \]\[(a_1-b_1)^2+(a_2-b_2)^2+...+(a_n-b_n)^2=r^2 \]可以發現,這個式子的右邊是一個常數,左邊有 \(n+1\) 項(\(n\) 項 \(2a_ib_i\) 和一個係數為 \(1\) 的 \((r^2-(b_1^2+b_2^2+...+b_n^2))\))
\[[ 2a_1 , 2a_2 , ... , 2a_n | a_1^2+a_2^2+...+a_n^2 ] \]就可以用高斯消元啦,讀入時注意一下就行了,程式碼如下:
#include<bits/stdc++.h> using namespace std; int n; double a[15][15],ans[15],in,add; int main(){ cin>>n; for(int i=1;i<=n+1;++i){ for(int j=1;j<=n;++j){ cin>>in; add+=in*in; a[i][j]=2*in; } a[i][n+1]=1; a[i][n+2]=add;add=0; } for(int i=1;i<=n+1;++i){ int MAX=i; for(int j=i+1;j<=n+1;++j){ if(fabs(a[j][i])>fabs(a[MAX][i])){ MAX=j; } } if(MAX!=i)swap(a[i],a[MAX]); double d=a[i][i]; for(int j=i;j<=n+2;++j){ a[i][j]/=d; } for(int j=i+1;j<=n+1;++j){ d=a[j][i]; for(int k=i;k<=n+2;++k){ a[j][k]-=a[i][k]*d; } } } ans[n+1]=a[n+1][n+2]; for(int i=n;i>=1;--i){ ans[i]=a[i][n+2]; for(int j=i+1;j<=n+1;++j){ ans[i]-=a[i][j]*ans[j]; } } for(int i=1;i<=n;++i){ cout<<fixed<<setprecision(3)<<ans[i]<<" "; } return 0; }