1. 程式人生 > 其它 >207. 球形空間產生器

207. 球形空間產生器

題目連結

207. 球形空間產生器

有一個球形空間產生器能夠在 \(n\) 維空間中產生一個堅硬的球體。

現在,你被困在了這個 \(n\) 維球體中,你只知道球面上 \(n+1\) 個點的座標,你需要以最快的速度確定這個 \(n\) 維球體的球心座標,以便於摧毀這個球形空間產生器。

注意: 資料保證有唯一解。

輸入格式

第一行是一個整數 \(n\)

接下來的 \(n+1\) 行,每行有 \(n\) 個實數,表示球面上一點的 \(n\) 維座標。

每一個實數精確到小數點後 \(6\) 位,且其絕對值都不超過 \(20000\)

輸出格式

有且只有一行,依次給出球心的 \(n\) 維座標(\(n\) 個實數),兩個實數之間用一個空格隔開。

每個實數精確到小數點後 \(3\) 位。

資料範圍

\(1≤n≤10\)

輸入樣例:

2
0.0 0.0
-1.0 1.0
1.0 0.0

輸出樣例:

0.500 1.500

解題思路

高斯消元

設球心座標為 \((x_1,x_2,\dots,x_n)\),依題意,有如下方程組(\(n+1\) 個等式,\(n+1\) 個未知數):

\[\left\{\begin{array}{l} \left(a_{01}-x_{1}\right)^{2}+\left(a_{02}-x_{2}\right)^{2}+\cdots+\left(a_{0 n}-x_{n}\right)^{2}=R^{2} \\ \left(a_{11}-x_{1}\right)^{2}+\left(a_{12}-x_{2}\right)^{2}+\cdots+\left(a_{1 n}-x_{n}\right)^{2}=R^{2} \\ \cdots \\ \left(a_{n1}-x_{1}\right)^{2}+\left(a_{n2}-x_{2}\right)^{2}+\cdots+\left(a_{n n}-x_{n}\right)^{2}=R^{2} \end{array}\right. \]

相鄰兩個等式作差,得:

\[\left\{\begin{array}{l} 2\left(a_{0\,1}-a_{1\,1}\right) x_{1}+2\left(a_{0\,2}-a_{1\,2}\right) x_{2}+\cdots+2\left(a_{0\,n}-a_{1\, n}\right) x_{n}=(a_{0\,1}^{2}-a_{1\,1}^{2})+(a_{0\,2}^{2}-a_{1\,2}^{2}) +\dots+(a_{0\,n}^{2}-a_{1\,n}^{2})\\ 2\left(a_{1\,1}-a_{2\,1}\right) x_{1}+2\left(a_{1\,2}-a_{2\,2}\right) x_{2}+\cdots+2\left(a_{1\, n}-a_{2\, n}\right) x_{n}=(a_{1\,1}^{2}-a_{2\,1}^{2})+(a_{1\,2}^{2}-a_{2\,2}^{2}) +\dots+(a_{1\,n}^{2}-a_{2\,n}^{2})\\ \cdots \\ 2\left(a_{{n-1}\,{1}}-a_{n\,1}\right) x_{1}+2\left(a_{n-1\,2}-a_{n\,2}\right) x_{2}+\cdots+2\left(a_{n-1\, n}-a_{n\, n}\right) x_{n}=(a_{n-1\,1}^{2}-a_{n\,1}^{2})+(a_{n-1\,2}^{2}-a_{n\,2}^{2}) +\dots+(a_{n-1\,n}^{2}-a_{n\,n}^{2})\\ \end{array}\right. \]

此即為 \(n\)

元一次方程組,可先將其轉化為 \(n\)\(n+1\) 列的矩陣形式,再進行高斯消元:

  • 先構造成如下形式(上三角矩陣):

\( \begin{bmatrix} 1 & & & \\ 0 & 1 & & \\ 0&0 & 1 & \end{bmatrix} \)

按對角線 \((r,c)\) 列舉,為了使除數不為 \(0\),找絕對值最大的 \(b[i][c]\),將對應的行換到 \(r\) 行,將 \(b[r][c]\) 化成 \(1\),每次按列將 \((r,c)\) 下面列消為 \(0\)

  • 最後構造如下形式(簡化階梯型矩陣):

\( \begin{bmatrix} 1 &0 & 0 & \\ 0 & 1 & 0 & \\ 0 & 0& 1& \end{bmatrix} \)

按列消,從最後一列往前,最終 \(n+1\) 列即為答案

  • 時間複雜度:\(O(n^3)\)

爬山法

程式碼

  • 高斯消元
// Problem: 球形空間產生器
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/description/209/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=15;
double a[N][N],b[N][N];
int n;
void Gauss()
{
	for(int r=1,c=1;r<=n;r++,c++)
	{
		int t=r;
		for(int i=r+1;i<=n;i++)
			if(fabs(b[i][c])>fabs(b[t][c]))t=i;
		for(int i=c;i<=n+1;i++)swap(b[r][i],b[t][i]);
		for(int i=n+1;i>=c;i--)b[r][i]/=b[r][c];
		for(int i=r+1;i<=n;i++)
			for(int j=n+1;j>=c;j--)b[i][j]-=b[i][c]*b[r][j];
	}
	for(int j=n;j>1;j--)
		for(int i=j-1;i>=1;i--)
		{
			b[i][n+1]-=b[j][n+1]*b[i][j];
			b[i][j]=0;
		}
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<=n;i++)
    	for(int j=1;j<=n;j++)scanf("%lf",&a[i][j]);
    for(int i=1;i<=n;i++)
    	for(int j=1;j<=n;j++)
    	{
    		b[i][j]=2*(a[i-1][j]-a[i][j]);
    		b[i][n+1]+=a[i-1][j]*a[i-1][j]-a[i][j]*a[i][j];
    	}
	Gauss();
	for(int i=1;i<=n;i++)printf("%.3lf ",b[i][n+1]);
    return 0;
}