高斯消元解线性方程组

本文详细介绍了高斯消元法,用于解决包含多个方程和未知数的线性方程组。通过构建增广矩阵并进行初等行变换,将方程组转化为阶梯型矩阵,进而求解。此外,还展示了如何将非线性方程组通过巧妙转化,转化为线性方程组,应用高斯消元法求解。最后,给出了具体的浮点型和布尔型模板代码实现,并提供了一个实例来说明如何运用这种方法解决球面上点的坐标问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

高斯消元: O ( n 3 ) O(n^3) O(n3)

  • 写出增广矩阵,将增广矩阵通过初等行变换变成阶梯型,然后往回带
  • 适用于求解包含 n n n个方程, n n n个未知数的多元线性方程组
    例如下式多元方程组:
    { a 1 , 1 ∗ x 1 + a 1 , 2 ∗ x i + ⋯ + a 1 , n ∗ x n = b 1 a 2 , 1 ∗ x 1 + a 2 , 2 ∗ x i + ⋯ + a 2 , n ∗ x n = b 2 ⋮ a n , 1 ∗ x 1 + a n , 2 ∗ x i + ⋯ + a n , n ∗ x n = b n \begin{cases} a_{1,1}*x_1 + a_{1,2}*x_i +\quad \cdots \quad+ a_{1, n}*x_n = b_1\\ a_{2,1}*x_1 + a_{2,2}*x_i +\quad \cdots \quad+ a_{2, n}*x_n = b_2 \\ \qquad \qquad \vdots \quad \\ a_{n,1}*x_1 + a_{n,2}*x_i +\quad \cdots \quad+ a_{n, n}*x_n = b_n\end{cases} a1,1x1+a1,2xi++a1,nxn=b1a2,1x1+a2,2xi++a2,nxn=b2an,1x1+an,2xi++an,nxn=bn
    写出其增广矩阵:
    [ a 1 , 1 a 1 , 2 ⋯ a 1 , n b 1 a 2 , 1 a 2 , 2 ⋯ a 2 , n b 2 ⋮ a n , 1 a n , 2 ⋯ a n , n b n ] \begin{bmatrix} a_{1,1}&a_{1,2} \quad \cdots \quad a_{1, n} \quad b_1\\a_{2,1}&a_{2,2} \quad \cdots \quad a_{2, n} \quad b_2 \\ \qquad \qquad \vdots \quad \\ a_{n,1}&a_{n,2} \quad \cdots \quad a_{n, n} \quad b_n \end{bmatrix}\quad a1,1a2,1an,1a1,2a1,nb1a2,2a2,nb2an,2an,nbn

通过初等行变换,变成阶梯型矩阵(取 n = 4 n = 4 n=4)为例:
[ a 1 , 1 a 1 , 2 a 1 , 3 a 1 , 4 b 1 0 a 2 , 2 a 2 , 3 a 2 , 4 b 2 0 0 a 3 , 3 a 3 , 4 b 3 0 0 0 a 4 , 4 b 4 ] \begin{bmatrix} a_{1,1}&a_{1,2}& a_{1,3} &a_{1, 4} & b_1\\ 0&a_{2,2}& a_{2,3} &a_{2, 4} & b_2 \\ 0&0& a_{3,3} &a_{3, 4} & b_3 \\ 0&0&0 &a_{4, 4} & b_4 \end{bmatrix}\quad a1,1000a1,2a2,200a1,3a2,3a3,30a1,4a2,4a3,4a4,4b1b2b3b4

高斯消元模板:

int gauss() // 浮点值
{
    int c, r;
    for(c = 0, r = 0; c < n; ++ c)
    {
        int t = r; // 找到最大行
        for(int i = r + 1; i < n; ++i)
        {
            if(fabs(a[i][c]) > fabs(a[t][c]))
                t = i;
        }
        if(fabs(a[t][c]) < eps) continue;
        for(int i = c; i <= n; ++i) swap(a[t][i], a[r][i]); // 把最大行换上去
        for(int i = n; i >= c; -- i)  a[r][i] /= a[r][c]; // 把这一行第一个数变为1
        for(int i = r + 1; i < n; ++i)
        {
            if(fabs(a[i][c]) > eps) // 不是0
            {
                for(int j = n; j >= c; --j)
                {
                    a[i][j] -= a[r][j] * a[i][c];
                }
            }
        }
        r ++;
    }
    if(r < n) {
    // 当系数全为0,常数不为0时,无解
        for(int i = r; i < n; ++i)
            if(fabs(a[i][n]) > eps) return 2;
        return 1;
    }
    
    for(int i = n - 1; i >= 0; -- i)
    {
        for(int j = i + 1; j < n; ++ j)
        {
            a[i][n] -= a[j][n] * a[i][j];
        }
    }
    return 0;
}
// 布尔值
// 异或性质:
// a ^ b ^ c = x, e ^ f = y.
// a ^ b ^ c ^ e ^ f = x ^ y
int gauss() 
{
    int c, r;
    for (c = 0, r = 0; c < n; c ++ )
    {
        int t = r;
        for (int i = r; i < n; i ++ )  // 找非零行
            if (a[i][c])
                t = i;

        if (!a[t][c]) continue;

        for (int i = c; i <= n; i ++ ) swap(a[r][i], a[t][i]);  // 将非零行换到最顶端
        for (int i = r + 1; i < n; i ++ )  // 用当前行将下面所有的列消成0
            if (a[i][c])
                for (int j = n; j >= c; j -- )
                    a[i][j] ^= a[r][j];

        r ++ ;
    }

    if (r < n)
    {
        for (int i = r; i < n; i ++ )
            if (a[i][n])
                return 2;  // 无解
        return 1;  // 有多组解
    }

    for (int i = n - 1; i >= 0; i -- )
        for (int j = i + 1; j < n; j ++ )
            a[i][n] ^= a[i][j] * a[j][n];

    return 0;  // 有唯一解
}

例题1(浮点型模板)

题目链接
AC代码

例题2(布尔型模板)

题目链接
AC代码

例题3(浮点型应用)

题目链接

题意:

在这里插入图片描述

Sol:

球体上所有点到球心的距离是相等的,因次只需求出一个点 ( x 1 , x 2 , x 3 ⋯   , x n ) (x_1, x_2, x_3 \cdots, x_n) (x1,x2,x3,xn),使得:
∑ j = 1 n ( a i , j − x j ) 2 = C \sum_{j=1}^n(a_{i,j} - x_j)^2 = C j=1n(ai,jxj)2=C
其中: C C C是常数, i ∈ [ 1 , n + 1 ] i \in [1, n+1] i[1,n+1],球面上第 i i i个点的坐标为 ( a i , 1 , a i , 2 ⋯   , a i , n ) (a_{i,1}, a_{i, 2} \cdots, a_{i, n}) (ai,1,ai,2,ai,n)
该方程组由 n + 1 n+1 n+1 n n n元二次方程构成,不是线性方程组。但是,我们可以两两相减,变成 n n n n n n元一次方程组,同时消去了常数 C C C
∑ j = 1 n ( a i , j 2 − a i + 1 , j 2 − 2 x j ( a i , j − a i + 1 , j ) ) = 0 i ∈ [ 1 , n ] \sum_{j=1}^n (a_{i,j}^2 - a_{i+1, j}^2 - 2x_j(a_{i,j} - a_{i+1,j})) = 0 \qquad i \in[1, n] j=1n(ai,j2ai+1,j22xj(ai,jai+1,j))=0i[1,n]
将变量放一边,常量放一边有:
∑ j = 1 n 2 ( a i , j − a i + 1 , j ) x j = ∑ j = 1 n ( a i , j 2 − a i + 1 , j 2 ) i ∈ [ 1 , n ] \sum_{j=1}^n 2(a_{i,j} - a_{i+1,j})x_j = \sum_{j=1}^n (a_{i,j}^2 - a_{i+1,j}^2) \qquad i \in [1, n] j=1n2(ai,jai+1,j)xj=j=1n(ai,j2ai+1,j2)i[1,n]
写成增广矩阵:
[ 2 ( a 1 , 1 − a 2 , 1 ) 2 ( a 1 , 2 − a 2 , 2 ) ⋯ 2 ( a 1 , n − a 2 , n ) ∑ j = 1 n ( a 1 , j 2 − a 2 , j 2 ) 2 ( a 2 , 1 − a 3 , 1 ) 2 ( a 2 , 2 − a 3 , 2 ) ⋯ 2 ( a 2 , n − a 3 , n ) ∑ j = 1 n ( a 2 , j 2 − a 3 , j 2 ) ⋮ 2 ( a n , 1 − a n + 1 , 1 ) 2 ( a n , 2 − a n + 1 , 2 ) ⋯ 2 ( a n , n − a n + 1 , n ) ∑ j = 1 n ( a n , j 2 − a n + 1 , j 2 ) ] \begin{bmatrix} 2(a_{1,1} - a_{2,1}) & 2(a_{1,2} - a_{2,2}) \quad \cdots \quad 2(a_{1,n} - a_{2,n}) \quad \sum_{j=1}^n (a_{1,j}^2 - a_{2,j}^2)\\ 2(a_{2,1} - a_{3,1}) & 2(a_{2,2} - a_{3,2}) \quad \cdots \quad 2(a_{2,n} - a_{3,n}) \quad \sum_{j=1}^n (a_{2,j}^2 - a_{3,j}^2)\\ \qquad \qquad \vdots \quad \\ 2(a_{n,1} - a_{n+1,1}) & 2(a_{n,2} - a_{n+1,2}) \quad \cdots \quad 2(a_{n,n} - a_{n+1,n}) \quad \sum_{j=1}^n (a_{n,j}^2 - a_{n+1,j}^2) \end{bmatrix}\quad 2(a1,1a2,1)2(a2,1a3,1)2(an,1an+1,1)2(a1,2a2,2)2(a1,na2,n)j=1n(a1,j2a2,j2)2(a2,2a3,2)2(a2,na3,n)j=1n(a2,j2a3,j2)2(an,2an+1,2)2(an,nan+1,n)j=1n(an,j2an+1,j2)
利用高斯消元求解

Code:
#include <bits/stdc++.h>
using namespace std;
const int N = 20;
const double eps = 1e-8;
int n;
double a[N][N], d[N][N];


int gauss()
{
    int c, r;
    for(r = 0, c = 0; c < n; ++ c)
    {
        int t = r;
        for(int i = r + 1; i < n; ++i) 
            if(fabs(a[i][c]) > fabs(a[t][c]))
                t = i;
        if(fabs(a[t][c]) < eps) continue;
        for(int i = c; i <= n; ++i) swap(a[t][i], a[r][i]);
        for(int i = n; i >= c; -- i) a[r][i] /= a[r][c];
        for(int i = r + 1; i < n; ++i)
        {
            if(fabs(a[i][c]) > eps)
            {
                for(int j = n; j >= c; -- j)
                {
                    a[i][j] -= a[i][c] * a[r][j];
                }
            }
        }
        r ++;
    }
    if(r < n)
    {
        for(int i = r; i < n; ++i)
            if(fabs(a[i][n]) > eps) return 2;
        return 1;
    }
    for(int i = n - 1; i >= 0; -- i)
        for(int j = i + 1; j < n; ++j)
            a[i][n] -= a[j][n] * a[i][j];
    return 0;
}

double pow2(double a, double b)
{
    return a * a - b * b;
}

int main()
{
    cin >> n;
    for(int i = 0; i <= n; ++i) 
        for(int j = 0; j < n; ++j)
            cin >> d[i][j];
    // 增广矩阵
    for(int i = 0; i < n; ++i)
        for(int j = 0; j <= n; ++j)
        {
            if(j == n)
            {
                for(int k = 0; k < n; ++k)
                {
                    a[i][j] += pow2(d[i][k], d[i + 1][k]);
                }
            }
            else
            {
                a[i][j] = 2 * (d[i][j] - d[i + 1][j]);
            }
        }
    int t = gauss();
    for(int i = 0; i < n; ++i) printf("%.3f ", a[i][n]);
}
好的,我可以为您介绍一下 C 语言实现高斯消线性方程组的方法。 首先,我们需要定义一个二维数组来存储系数矩阵和常数向量,例如: ``` float A[N][N+1]; ``` 其中,N 表示方程组的未知数个数。这个数组的第 i 行第 j 列表示系数矩阵中第 i 行第 j 列的素,而最后一列则是常数向量。 接下来,我们需要进行高斯消的主要操作。具体步骤如下: 1. 针对每一列,找到该列中绝对值最大的素,并将该素所在的行与当前行交换。 2. 对于第 i 行,将其第 i 个素除以该行第 i 列的系数,以使得第 i 个素变为 1。 3. 对于第 j 列(j>i),将第 j 行减去第 i 行的系数乘以第 j 列的素,以使得第 j 列的第 i 个素变为 0。 4. 重复步骤 1-3,直到所有的未知数都求出来。 最后,我们可以通过回代法计算出每个未知数的值,具体方法如下: 1. 从最后一行开始,计算出该行未知数的值。 2. 对于第 i 行(i<n),计算出第 i 个未知数的值,即将第 i 行第 i+1 至第 n 个未知数的值带入方程中,计算出第 i 个未知数的值。 3. 重复步骤 1-2,直到所有的未知数都求出来。 以上就是 C 语言实现高斯消线性方程组的基本步骤。需要注意的是,在实际应用中,可能会遇到系数矩阵不满足条件、有多或无等问题,需要根据具体情况进行特殊处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

W⁡angduoyu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值