P4035 [JSOI2008] 球状空間ジェネレーター (ガウス消去法)

トピックの説明

n 次元空間に固体の球を生成する球空間ジェネレーターがあります。さて、あなたはこの n 次元の球の中に閉じ込められています。球上の n+1 個の点の座標しか知りません。破壊するには、この n 次元の球の中心の座標をできるだけ早く決定する必要があります。この球状空間を利用してデバイスを生成します。

入力フォーマット

最初の行は整数 (1≤N≤10) です。次の n+1 行には、各行に n 個の実数があり、球上の点の n 次元座標を表します。各実数は小数点以下 6 桁までの精度があり、その絶対値は 20000 を超えません。

出力フォーマット

球の中心の n 次元座標 (n 個の実数) を順番に示す 1 本の線があり、2 つの実数はスペースで区切られています。各実数は小数点以下 3 桁まで正確です。データには解決策があることが保証されています。回答は、スコア付けされる標準出力とまったく同じである必要があります。

解析:

球の中心が球の中心から点までの距離と同じであるとします。2 つの隣接する方程式を減算すると、未知数が左にシフトします。

円の中心の位置を取得するために解くことができる n 個の未知の項目と n 個の方程式があります。

#include<bits/stdc++.h>
using namespace std;
inline double read() {
	char ss = getchar();
	int f = 1;
	double x = 0;
	while (ss < '0' || ss>'9') {
		if (ss == '-') {
			f = -1;
		}
		ss = getchar();
	}
	while (ss >= '0' && ss <= '9') {
		x = x * 10 + ss - '0';
		ss = getchar();
	}
	return x * f;
}

double a[20][20], c[20][20];  // c储存系数 b是每一个方程的值
int n;
double eps = 1e-7;

int main() {
	n = read();
	for (int i = 1; i <= n + 1; 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++) {
			c[i][j] = 2 * (a[i][j] - a[i + 1][j]);
			c[i][n+1] += a[i][j] * a[i][j] - a[i + 1][j] * a[i + 1][j];// 累加 平方 
		}
	}
		//高斯消元
		for (int i = 1; i <= n; i++) {
			int max = i;
			for (int j = i+1; j <= n; j++) {
				if (fabs(c[j][i]) > fabs(c[max][i])) max = j; //选最大的避免选到0
			}

			//因为这个一定有解所以没有判断是否有解的步骤
			// 交换
			for (int j = 1; j <= n+1; j++) {
				swap(c[i][j], c[max][j]);
			}
			 // c[i][n+1]是等式的值

			//消元

			for (int j = n+1; j >= 1; j--) {
				c[i][j] = c[i][j] / c[i][i]; //对角线化1
			}
			

			for (int j = 1; j <= n; j++) {
				if (j != i) {
					double temp = c[j][i] / c[i][i]; // 乘以系第i列化为0
					for (int k = 1; k <= n+1; k++) {
						c[j][k] -= c[i][k] * temp;
					}
				}
			}
		}
		
		for (int i = 1; i <= n; i++) {
			printf("%0.3lf ",c[i][n+1]);
		}
	return 0;
}

おすすめ

転載: blog.csdn.net/zhi6fui/article/details/129476867