被学长教会的高斯消元法Gauss

昨天学长教了我高斯消元法。

这里用一个栗子来模拟一下Gauss的流程。

真的通俗易懂!这里是洛谷题目链接

 

这就是例子

x-2y+3z=6
4x-5y+6z=12
7x-8y+10z=21 

 

先将它转化为矩阵

1 -2 3 6
4 -5 6 12
7 -8 10 21

 

解决这个方程组

我们会希望它变成如下形式

1 0 0 a
0 1 0 b
0 0 1 c

 

这样就可以表示为$x=a$,$y=b$,$z=cx=a$,$y=b$,$z=c$,$x=a$,$y=b$,$z=c$

我们使用高斯消元,就要一步一步将每个未知数约去。

这种方法是以列为单位消去的

首先我们将第一列转化为1 0 0的形式

在这里要注意一下,我们往往是将这个系数绝对值最大的方程转移到被减的这一行,这样就可以减小误差

所以我们先将矩阵变成这样 

7 -8 10 21
4 -5 6 12
1 -2 3 6

 

然后将正在处理的方程式化简,让正被处理的系数化1

1 -8/7 10/7 3
4 -5 6 12
1 -2 3 6

 

然后使用加减法将第二个与第三个方程组的第一个系数化0

1 -8/7 10/7 3
0 -3/7 2/7 0
0 -6/7 11/7 3

 

然后这时候第一列就被化简完成

同理我们化去第二行与第三行,步骤如下:

1.化简第二行

1 -8/7 10/7 3
0 1 -2/3 0
0 -6/7 11/7 3

 

2.用第一行减第二行×(-8/7),第三行减第二行×(-6/7)

1 0 2/3 3
0 1 -2/3 0
0 0 1 3 

 

3.不需要化简第三行,所以直接用第一行减去第三行×2/3,第二行减去第三行×(-2/3)

1 0 0 1
0 1 0 2
0 0 1 3

 

最后我们就得到了一组解x=1,y=2,y=3x=1,y=2,y=3x=1,y=2,y=3 。

所以高斯消元其实是运用了小学解方程组的加减法的讷。

代码请见我的博客《从2017年暑假到现在手打的模板_之三十二

我还是老老实实地贴了上来: 

//Guss
#include <bits/stdc++.h>
using namespace std;

int n;
double f[105][105];
const double eps=1e-8;

int main()
{
    scanf("%d",&n);
    for (int i=0;i<n;i++)//读入系数和值
    for (int j=0;j<=n;j++) scanf("%lf",&f[i][j]);
    for (int i=0;i<n;i++) {
        int ch=i;
        for (int j=i;j<n;j++)//选择绝对值最大的减少误差
        if (fabs(f[j][i]-f[ch][i])<=eps) ch=j;
        for (int j=0;j<=n;j++) swap(f[i][j],f[ch][j]);//交换
        if (fabs(f[i][i])<=eps) {//无解情况
            printf("No Solution\n");
            return 0;//如果当前位置为零 则无解 0x=A
        }
        for (int j=i+1;j<=n;j++) f[i][j]/=f[i][i];//系数化1
        //自己那位不必要除 无影响
        for (int j=0;j<n;j++)
        if (i!=j)
        for (int k=i+1;k<=n;k++) f[j][k]-=f[j][i]*f[i][k];
        //加减法去掉系数值
    }
    for (int i=0;i<n;i++) printf("%.2lf\n",f[i][n]);//输出
    return 0;
}

 

posted @ 2018-02-26 20:53  fuyan0101  阅读(392)  评论(1编辑  收藏  举报