洛谷——P3389 【模板】高斯消元法

P3389 【模板】高斯消元法

以下内容都可省略,直接转大佬博客%%%

高斯消元总结

只会背板子的蒟蒻,高斯消元是什么,不知道诶,看到大佬们都会了这个水题,蒟蒻只好也来切一切

高斯消元最大用途就是解多元一次方程组——引自某大佬原话

的确是这样的,那么如何去做呢?

类比二元一次方程组:

$a_1x+b_1y=c_1$

$a_2x+b_2y=c_2$

emmm,怎么做呢?消去一项!嗯。

也就是把第$i$个方程的第$i$项变成1

$frac{a_1}{a_1}x+frac{b_1}{a_1}y=frac{c_1}{a_1}$

也就是$x+frac{b_1}{a_1}y=frac{c_1}{a_1}$

再用这个式子消去第$i+1$到$n$方程的第$i$项,

$frac{a_2}{a_2}x+frac{b_2}{a_2}y=frac{c_2}{a_2}$

也就是$x+frac{b_2}{a_2}y=frac{c_2}{a_2}$

用这一项减去上一项$0+(frac{b_2}{a_2}-frac{b_1}{a_1})y=frac{c_2}{a_2}-frac{c_1}{a_1}$

由于将每一项的系数都化为一比较麻烦,我们尝试直接消去那一项

$a_1x+b_1y=c_1$

$a_2x+b_2y=c_2$

第二项变成$a_2 imes frac{a_1}{a_2}x+b_2 imes frac{a_1}{a_2}y=c_2 imes frac{a_1}{a_2}$

消去第一项$(a_2 imes frac{a_1}{a_2}-a_1)x+(b_2 imes frac{a_1}{a_2}-b_1)y=c_2 imes frac{a_1}{a_2}-c_1$

这样是可行的,同样是把第二个方程组的第一项系数化为$0$

for(int i=1;i<=n;i++){
        if(!a[i][i]) return puts("No Solution
"),0;
        for(int j=i+1;j<=n;j++)
            for(int k=n+1;k>=i;k--)
                a[j][k]=a[j][k]*a[i][i]/a[j][i]-a[i][k];
}
//消元

不过大佬们都是这样写的,见代码:

$a_1x+b_1y=c_1$

$(a_2-frac{a_2}{a_1} imes a_1)x+(b_2-frac{a_2}{a_1} imes b_1)y=c_2-frac{a_2}{a_1} imes c_1$

貌似这才是正确的操作,相当于把第一个方程同除以$a_1$,第二个方程减去$a_2 imes...$

回代过程略。。。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>

using namespace std;

double a[205][205],x[205];
int n;

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)//n个方程
        for(int j=1;j<=n+1;j++)//n项以及最后c
            scanf("%lf",&a[i][j]);
    
    for(int i=1;i<=n;i++){//枚举每一方程
        if(!a[i][i]) return puts("No Solution
"),0;
        for(int j=i+1;j<=n;j++)
            for(int k=n+1;k>=i;k--)
                a[j][k]-=a[i][k]*a[j][i]/a[i][i];
    }//消元 
    
    for(int i=n;i;i--){
        x[i]=a[i][n+1];
        for(int j=n;j>i;j--) x[i]-=a[i][j]*x[j];
        x[i]/=a[i][i];
    }//回代 
    for(int i=1;i<=n;i++)
        printf("%.2lf
",x[i]);
    
    return 0;
}
原文地址:https://www.cnblogs.com/song-/p/9776102.html