AcWing 207. 球形空间产生器 (高斯消元 + 推公式)

总所周知,一个球体上的所有的点到球心的距离(即半径)是相等的.

我们假设球心的坐标为(x_1, x_2, x_3, ...x_n),半径为C(C为常数), 并记这n + 1个点的坐标为a_{i, j}(i=1, 2, 3, ..., n, n + 1. j =1, 2, 3, ..., n)显然,\sum_{i=1}^{n+1}(a_{i, j}-x_j)^2=C, 首先,这个方程是一定有解的,因为一共有n + 1个方程和n + 1个未知数(球心的坐标和半径大小),但是这是一个二元方程组,要直接解出来还是有点麻烦的,于是我们可以对相邻的两个方程作差进行消元.得到:

\sum_{i=1}^{n}(a_{i, j}^2-a_{i + 1, j}^2-2x_j(a_{i, j}-a_{i + 1, j}))=0

移项得,

2\sum_{i=1}^{n}x_j(a_{i, j}-a_{i + 1, j})=\sum_{j=1}^{n}(a_{i, j}^2 - a_{i + 1, j}^2)        

```
#include <bits/stdc++.h>
using namespace std;
const int N = 20;
const double eps = 1e-8;
double a[N][N], b[N], c[N][N];
int n;
signed main(){
    cin >> n;
    for (int i = 1; i <= n + 1; ++i)
        for (int j = 1; j <= n; ++j)
            cin >> a[i][j];
    /* c:系数矩阵, b:常数,二者构成增广矩阵 */
    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]);
            b[i] += a[i][j] * a[i][j] -a[i + 1][j] * a[i + 1][j];
        }            

    /* 高斯消元 */
    /* 枚举每一列, 行数和列数是相等的(不包含最后的常数项) */
    for (int i = 1; i <= n; ++i){
        /* 找到x[i]系数不为0的一个方程 */
        for (int j = i; j <= n; ++j){
            if (fabs(c[j][i]) > eps){
                for (int k = 1; k <= n; ++k)
                    swap(c[i][k], c[j][k]);
                swap(b[i], b[j]);
            }
        }
        /* 消去其他方程x[i]的系数 */
        for (int j = 1; j <= n; ++j){
            if (i == j)
                continue;
            double rate = c[j][i] / c[i][i];
            for (int k = i; k <= n; ++k)
                c[j][k] -= c[i][k] * rate;
            b[j] -= b[i] * rate;
        }
    }
    for (int i = 1; i <= n; ++i)
        printf("%.3f ", b[i] / c[i][i]);

}
```

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值