洛谷题单指南-基础线性代数-P4035 [JSOI2008] 球形空间产生器
原题链接:https://www.luogu.com.cn/problem/P4035
题意解读:已知n维空间的n+1个点,求圆心坐标。
解题思路:(题解由Chatgpt生成)



借助每相邻两个点,一共可以得到n个这样的方程,n个未知数,可以使用高斯消元求解。
矩阵:a[i][j] = 2*(p[i+1][j]-p[i][j])
右侧:a[i][n+1] = sum(p[i+1][j]^2 - p[i][j]^2)
得到一个:n × (n+1)的增广矩阵。
100分代码:(代码由Chatgpt生成)
#include <bits/stdc++.h>
using namespace std;
const int N = 20;
const double EPS = 1e-8;
// a 为高斯消元用的增广矩阵,规模 n * (n+1)
// p 为输入的点坐标,共 n+1 个点,每个点是 n 维
double a[N][N];
double p[N][N];
int n; // 维度 n,同时未知数个数也是 n
int gauss()
{
// 行指针:当前要处理的主元行
int row = 1;
for(int col = 1; col <= n; col++)
{
// 选主元:在当前列 col 中寻找绝对值最大的行
int t = row;
for(int i = row + 1; i <= n; i++)
if(fabs(a[i][col]) > fabs(a[t][col]))
t = i;
// 主元接近 0,说明该列无法作为主元,跳过
if(fabs(a[t][col]) < EPS) continue;
// 将主元行交换到当前行
for(int i = col; i <= n + 1; i++)
swap(a[t][i], a[row][i]);
// 把主元归一化,使 a[row][col] 变为 1
for(int i = n + 1; i >= col; i--)
a[row][i] /= a[row][col];
for(int i = 1; i <= n; i++)
{
if(i == row) continue;
// 用当前主元行消去其他行的该列
for(int j = n + 1; j >= col; j--)
a[i][j] -= a[row][j] * a[i][col];
}
// 处理下一行
row++;
}
// 若未能形成 n 个主元行,检查是否有矛盾行
if(row <= n)
{
for(int i = row; i <= n; i++)
if(fabs(a[i][n + 1]) > EPS)
return -1;
// 存在自由元,返回 0
return 0;
}
// 唯一解
return 1;
}
int main()
{
cin >> n;
// 输入 n+1 个点,每个点 n 维
for(int i = 1; i <= n + 1; i++)
for(int j = 1; j <= n; j++)
cin >> p[i][j];
// 构造线性方程组:
// 由 |x - p_i|^2 = |x - p_{i+1}|^2 推得
// 2 * (p_{i+1} - p_i) · x = |p_{i+1}|^2 - |p_i|^2
// 共 n 个方程,n 个未知数(x 的各维坐标)
for(int i = 1; i <= n; i++)
{
// 系数部分
for(int j = 1; j <= n; j++)
a[i][j] = 2 * (p[i + 1][j] - p[i][j]);
double rhs = 0;
// 常数项:平方和之差
for(int j = 1; j <= n; j++)
rhs += p[i + 1][j] * p[i + 1][j] - p[i][j] * p[i][j];
a[i][n + 1] = rhs;
}
// 求解增广矩阵
gauss();
// 输出解(球心坐标),保留三位小数
for(int i = 1; i <= n; i++)
printf("%.3lf ", a[i][n + 1]);
return 0;
}
浙公网安备 33010602011771号