高斯消元专题

来源:互联网 发布:mac下python开发环境 编辑:程序博客网 时间:2024/06/05 19:16

高斯消元法可用来找出下列方程组的解或其解的限制:捕获1
这个算法的原理是:
首先,要将L1以下的等式中的x消除,然后再将L2以下的等式中的y消除。这样可使整个方程组变成一个三角形似的格式。之后再将已得出的答案一个个地代入已被简化的等式中的未知数中,就可求出其余的答案了。
捕获2
第二步,就是由尾至头地将已知的答案代入其他等式中的未知数。第一个答案就是:捕获3
然后就可以将z代入L2中,立即就可得出第二个答案:捕获4
之后,将z和y代入L1之中,最后一个答案就出来了:捕获5
就是这样,这个方程组就被高斯消元法解决了

下面是n元线性方程组的一般形式:
捕获6
我们可以把它表示为增广矩阵的形式:
捕获7
然后就可以用高斯消元法在计算机上求解方程组了

对于刚才的例子,我们把它写成增广矩阵的形式:
捕获8

跟着以上的方法来运算,这个矩阵可以转变为以下的样子:
捕获9
这矩阵叫做“行梯阵式”。

最后,可以利用同样的算法产生以下的矩阵,便可把所得出的解或其限制简明地表示出来:
捕获10
最后这矩阵叫做“简化行梯阵式”,亦是高斯-约当消元法指定的步骤。

自由变元(有效的方程个数-变量数):
例子:x+y+z=1,这个方程是有无数解的,但是自由变元只有两个,但是每个变量都是无法确定的,只有当把两个自由变元的值确定了,这个方程便有了唯一解。

模板讲解:

普通版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
constint MAXN=50; int a[MAXN][MAXN];//增广矩阵
int x[MAXN];//解集 boolfree_x[MAXN];//标记是否是不确定的变元
inlineintgcd(inta,intb) {
    intt;
    while(b!=0) {
        t=b;
        b=a%b;
        a=t;
    }
    returna;
}
inlineint lcm(inta,intb) {
    returna/gcd(a,b)*b;//先除后乘防溢出 }
 // 高斯消元法解方程组(Gauss-Jordan elimination).(-2表示有浮点数解,但无整数解,
//-1表示无解,0表示唯一解,大于0表示无穷解,并返回自由变元的个数)
//有equ个方程,var个变元。增广矩阵行数为equ,分别为0到equ-1,列数为var+1,分别为0到var.
int Gauss(intequ,intvar) {
    inti,j,k;
    intmax_r;// 当前这列绝对值最大的行.    int col;//当前处理的列    intta,tb;
    intLCM;
    inttemp;
    intfree_x_num;
    intfree_index;
    for(inti=0; i<=var; i++) {
        x[i]=0;
        free_x[i]=true;
    }
    //转换为阶梯阵.    col=0; // 当前处理的列    for(k = 0; k <equ&& col <var; k++,col++) {
        // 枚举当前处理的行.
// 找到该col列元素绝对值最大的那行与第k行交换.(为了在除法时减小误差)        max_r=k;
        for(i=k+1; i<equ; i++) {
            if(abs(a[i][col])>abs(a[max_r][col])) max_r=i;
        }
        if(max_r!=k) {
            // 与第k行交换.            for(j=k; j<var+1; j++) swap(a[k][j],a[max_r][j]);
        }
        if(a[k][col]==0) {
            // 说明该col列第k行以下全是0了,则处理当前行的下一列.            k--;
            continue;
        }
        for(i=k+1; i<equ; i++) {
            // 枚举要删去的行.            if(a[i][col]!=0) {
                LCM = lcm(abs(a[i][col]),abs(a[k][col]));
                ta = LCM/abs(a[i][col]);
                tb = LCM/abs(a[k][col]);
                if(a[i][col]*a[k][col]<0)tb=-tb;//异号的情况是相加                for(j=col; j<var+1; j++) {
                    a[i][j] = a[i][j]*ta-a[k][j]*tb;
                }
            }
        }
    }
  
    // 1. 无解的情况: 化简的增广阵中存在(0, 0, ..., a)这样的行(a != 0).    for (i = k; i<equ; i++) {
        if(a[i][col] != 0) return-1;
    }
    // 2. 无穷解的情况: 在var * (var + 1)的增广阵中出现(0, 0, ..., 0)这样的行,即说明没有形成严格的上三角阵.    // 且出现的行数即为自由变元的个数.     // 对于无穷解来说,如果要判断哪些是自由变元,那么初等行变换中的交换就会影响,则要记录交换.     if (k <var) {
        // 首先,自由变元有var - k个,即不确定的变元至少有var - k个.        for (i = k - 1; i>= 0; i--) {
            // 第i行一定不会是(0, 0, ..., 0)的情况,因为这样的行是在第k行到第equ行.            // 同样,第i行一定不会是(0, 0, ..., a), a != 0的情况,这样的无解的.            free_x_num = 0; // 用于判断该行中的不确定的变元的个数,如果超过1个,则无法求解,它们仍然为不确定的变元.            for (j = 0; j <var; j++) {
                if(a[i][j] != 0 &&free_x[j]) free_x_num++, free_index = j;
            }
            if(free_x_num> 1) continue;// 无法求解出确定的变元.             // 说明就只有一个不确定的变元free_index,那么可以求解出该变元,且该变元是确定的.             temp = a[i][var];
            for(j = 0; j <var; j++) {
                if(a[i][j] != 0 && j != free_index) temp -= a[i][j] * x[j];
            }
            x[free_index] = temp / a[i][free_index];// 求出该变元.             free_x[free_index] = 0; // 该变元是确定的.        }
        returnvar - k; // 自由变元有var - k个.    }
    // 3. 唯一解的情况: 在var * (var + 1)的增广阵中形成严格的上三角阵.    // 计算出Xn-1, Xn-2 ... X0.     for (i = var - 1; i>= 0; i--) {
        temp = a[i][var];
        for(j = i + 1; j <var; j++) {
            if(a[i][j] != 0) temp -= a[i][j] * x[j];
        }
        if(temp % a[i][i] != 0) return-2; // 说明有浮点数解,但无整数解.         x[i] = temp / a[i][i];
    }
    return0;
}

解浮点数方程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
doublea[MAXN][MAXN],x[MAXN];//方程的左边的矩阵存在a中和等式右边的值存在x中,求解之后x存的就是结果intequ,var;//方程数和未知数个数
/*
*返回0表示无解,1表示有解
*/ int Gauss() {
    inti,j,k,col,max_r;
    for(k=0,col=0; k<equ&&col<var; k++,col++) {
        max_r=k;
        for(i=k+1; i<equ; i++)
            if(fabs(a[i][col])>fabs(a[max_r][col]))
                max_r=i;
        if(fabs(a[max_r][col]) <eps)return0;
        if(k!=max_r) {
            for(j=col; j<var; j++)
                swap(a[k][j],a[max_r][j]);
            swap(x[k],x[max_r]);
        }
        x[k]/=a[k][col];
        for(j=col+1; j<var; j++)a[k][j]/=a[k][col];
        a[k][col]=1;
        for(i=0; i<equ; i++)
            if(i!=k) {
                x[i]-=x[k]*a[i][k];
                for(j=col+1; j<var; j++)a[i][j]-=a[k][j]*a[i][col];
                a[i][col]=0;
            }
    }
    return1;
}

对2取模的01方程组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
constint MAXN = 40;//有equ个方程,var个变元。增广矩阵行数为equ,列数为var+1,分别为0到var intequ,var; inta[MAXN][MAXN]; //增广矩阵
int x[MAXN]; //解集 intfree_x[MAXN];//用来存储自由变元(多解枚举自由变元可以使用)intfree_num;//自由变元的个数//返回值为-1表示无解,为0是唯一解,否则返回自由变元个数
int Gauss() {
    intmax_r,col,k;
    free_num = 0;
    for(k = 0, col = 0 ; k <equ&& col <var ; k++, col++) {
        max_r = k;
        for(inti = k+1; i<equ; i++) {
            if(abs(a[i][col]) >abs(a[max_r][col]))
                max_r = i;
        }
        if(a[max_r][col] == 0) {
            k--;
            free_x[free_num++] = col;//这个是自由变元            continue;
        }
        if(max_r != k) {
            for(intj = col; j < var+1; j++)
                swap(a[k][j],a[max_r][j]);
        }
        for(inti = k+1; i<equ; i++) {
            if(a[i][col] != 0) {
                for(intj = col; j < var+1; j++)
                    a[i][j] ^= a[k][j];
            }
        }
    }
    for(inti = k; i<equ; i++)
        if(a[i][col] != 0)
            return-1;//无解     if(k <var) returnvar-k;//自由变元个数    //唯一解,回代     for(inti = var-1; i>= 0; i--) {
        x[i] = a[i][var];
        for(intj = i+1; j <var; j++)
            x[i] ^= (a[i][j] && x[j]);
    }
    return0;
}

推荐专题练习:hust
Click here!!!

0 0