欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

高斯消元-洛谷模板题P3389

程序员文章站 2022-07-12 14:20:01
...

题目大意:

给你n个方程的系数(即 n × ( n + 1 ) n \times (n+1) n×(n+1)的矩阵),让你求每个数的解.
n ≤ 100 n \leq 100 n100

算法:高斯消元

思想:

先用一个式子 E E E将其他式子中的一个未知数 x x x给消掉.那么其他式子就与 x x x无关了。
这个时候,忽略掉 E E E的存在,剩下的式子少了一个未知数 x x x并且仍然符合子问题.继续求解直到只剩下一个只含一个未知数的式子(即一个解).然后将这个解一个一个回代到其他式子中即可得到所有解。

具体在编程实现的时候,选择绝对值最大的系数作为式 E E E能够最小化精度误差

算法步骤:
1.对于每一列(即每个未知数),找出系数绝对值最大所在的行,将其整行交换到第一行.(若不存在非零系数,则该方程组无唯一解)
2.对第一行,将最左边的系数归一化.
3.对下面的所有行,与第一行相消使得最左边的系数归0.
4.此时除了第一行,其他行与最左未知数无关,构成子问题继续求解.

5.求出最后一个未知数的解后,从最后一行往上逆推求所有解。

模板:

const int maxn = 200 + 5;
const double eps = 1e-7;
double a[maxn][maxn] , ans[maxn];
int n;
bool guess ()
{
    // 从第一列开始
    bool ok = true;
    for (int i = 1 ; i <= n ; i++){
        // 找*绝对值*系数最大所在行,将其swap到第一行
        int p = i;
        for (int j = i + 1 ; j <= n ; j++)
            if (fabs(a[j][i]) > fabs(a[p][i])) p = j;
        // 不存在非零系数,则不存在唯一解
        if (fabs(a[i][p]) < eps){
            ok = false;
            break;
        }
        swap(a[p] , a[i]);
        // 将第一行对最左边的系数归一化
        double d = a[i][i];
        for (int j = i ; j <= n + 1 ; j++)
            a[i][j] /= d;
        // 用第一行消去其他行的最左系数
        for (int j = i + 1 ; j <= n ; j++){
            double d = a[j][i];
            for (int k = i ; k <= n + 1 ; k++){
                a[j][k] -= d * a[i][k];
            }
        }
    }
    if (!ok){
        return false;
    }
    // 回代操作
    ans[n] = a[n][n + 1];
    for (int i = n - 1 ; i >= 1 ; i--){
        ans[i] = a[i][n + 1];
        for (int j = i + 1 ; j <= n ; j++)
            ans[i] -= a[i][j] * ans[j];
    }
    return true;
}

关于其他情况的讨论:

1.无解
2.存在*元

相关标签: 线性代数 算法