高斯消元法可用来找出下列方程组的解或其解的限制:
这个算法的原理是:
首先,要将L1以下的等式中的x消除,然后再将L2以下的等式中的y消除。这样可使整个方程组变成一个三角形似的格式。之后再将已得出的答案一个个地代入已被简化的等式中的未知数中,就可求出其余的答案了。
第二步,就是由尾至头地将已知的答案代入其他等式中的未知数。第一个答案就是:
然后就可以将z代入L2中,立即就可得出第二个答案:
之后,将z和y代入L1之中,最后一个答案就出来了:
就是这样,这个方程组就被高斯消元法解决了
下面是n元线性方程组的一般形式:
我们可以把它表示为增广矩阵的形式:
然后就可以用高斯消元法在计算机上求解方程组了
跟着以上的方法来运算,这个矩阵可以转变为以下的样子:
这矩阵叫做“行梯阵式”。
最后,可以利用同样的算法产生以下的矩阵,便可把所得出的解或其限制简明地表示出来:
最后这矩阵叫做“简化行梯阵式”,亦是高斯-约当消元法指定的步骤。
自由变元(有效的方程个数-变量数):
例子: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,
int
b) {
int
t;
while
(b!=0) {
t=b;
b=a%b;
a=t;
}
return
a;
}
inlineint lcm(inta,
int
b) {
return
a/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;
int
LCM;
int
temp;
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;
// 该变元是确定的.
}
return
var - 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];
}
return
0;
}
|
解浮点数方程
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
|
double
a[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)
return
0;
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;
}
}
return
1;
}
|
对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;
int
a[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
(
int
j = 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
(
int
j = 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)
return
var-k;
//自由变元个数
//唯一解,回代
for
(inti = var-1; i>= 0; i--) {
x[i] = a[i][var];
for
(
int
j = i+1; j <var; j++)
x[i] ^= (a[i][j] && x[j]);
}
return
0;
}
|
推荐专题练习:hust
Click here!!!