生活随笔
收集整理的這篇文章主要介紹了
高斯消元法讲解
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
高斯消元的本質就是化簡成一個階梯式的行列式。
首先線性方程組的解有以下三種情況:
高斯消元的步驟分為以下四步:
- 枚舉每一行找到當前行(包括當前行)下面的,當前列的絕對值最大的一個數。
- 將其絕對值最大的一行移到上面
- 將改行的第一個數變成1
- 將下面所有的行的當前列都清成0
例子:
注意:這里剛開始是第一行和第一列,以此類推就會化簡成一個階梯行列式。
https://www.acwing.com/problem/content/description/885/
按照上面的步驟模擬的代碼如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std
;
const int N
=110;
const double eps
=1e-6;
double a
[N
][N
];
int n
;
void print()
{for(int i
=1;i
<=n
;i
++){for(int j
=1;j
<=n
+1;j
++)cout
<<a
[i
][j
]<<" ";cout
<<endl
;}cout
<<endl
;
}
int gauss()
{int c
,r
;for(c
=1,r
=1;c
<=n
;c
++){int t
=r
;for(int i
=r
;i
<=n
;i
++){if(fabs(a
[i
][c
])>fabs(a
[t
][c
])) t
=i
;}if(fabs(a
[t
][c
])<eps
) continue;for(int i
=c
;i
<=n
+1;i
++) swap(a
[r
][i
],a
[t
][i
]);for(int i
=n
+1;i
>=c
;i
--) a
[r
][i
]=a
[r
][i
]/a
[r
][c
];for(int i
=r
+1;i
<=n
;i
++){if (fabs(a
[i
][c
]) > eps
)for(int j
=n
+1;j
>=c
;j
--){a
[i
][j
]-=a
[i
][c
]*a
[r
][j
];}} r
++;}if (r
<= n
){for (int i
= r
; i
<= n
; i
++ )if (fabs(a
[i
][n
+1]) > eps
)return 2;return 1;}for (int i
= n
; i
>=1; i
-- )for (int j
= i
+ 1; j
<= n
; j
++ )a
[i
][n
+1] -= a
[j
][n
+1] * a
[i
][j
];return 0;
}
int main(void)
{cin
>>n
;for(int i
=1;i
<=n
;i
++){for(int j
=1;j
<=n
+1;j
++)cin
>>a
[i
][j
];}int t
=gauss();if (t
== 0){for (int i
= 1; i
<= n
; i
++ ) printf("%.2lf\n", a
[i
][n
+1]);}else if (t
== 1) puts("Infinite group solutions");else puts("No solution");return 0;
}
下面開始回答一些常見的不懂的問題:
問題一:為啥化簡為 1的操作,和清零的操作都要倒著推。
當然你也可以正著推,不過你要用一個變量來記錄一下開頭的元素的值。化簡都除以這個值就行了。
不過著稍微有點麻煩。
那么此時的代碼就如下所示:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std
;
const int N
=110;
const double eps
=1e-6;
double a
[N
][N
];
int n
;
void print()
{for(int i
=1;i
<=n
;i
++){for(int j
=1;j
<=n
+1;j
++)cout
<<a
[i
][j
]<<" ";cout
<<endl
;}cout
<<endl
;
}
int gauss()
{int c
,r
;for(c
=1,r
=1;c
<=n
;c
++){int t
=r
;for(int i
=r
;i
<=n
;i
++){if(fabs(a
[i
][c
])>fabs(a
[t
][c
])) t
=i
;}if(fabs(a
[t
][c
])<eps
) continue;for(int i
=c
;i
<=n
+1;i
++) swap(a
[r
][i
],a
[t
][i
]);double x
=a
[r
][c
];for(int i
=c
;i
<=n
+1;i
++) a
[r
][i
]=a
[r
][i
]/x
;for(int i
=r
+1;i
<=n
;i
++){if (fabs(a
[i
][c
]) > eps
){double x
=a
[i
][c
];for(int j
=c
;j
<=n
+1;j
++){a
[i
][j
]-=x
*a
[r
][j
];}}} r
++;}if (r
<= n
){for (int i
= r
; i
<= n
; i
++ )if (fabs(a
[i
][n
+1]) > eps
)return 2;return 1;}for(int i
=n
;i
>=1;i
--)for(int j
=i
+1;j
<=n
;j
++)a
[i
][n
+1]-=a
[j
][n
+1]*a
[i
][j
];return 0;
}
int main(void)
{cin
>>n
;for(int i
=1;i
<=n
;i
++){for(int j
=1;j
<=n
+1;j
++)cin
>>a
[i
][j
];}int t
=gauss();if (t
== 0){for (int i
= 1; i
<= n
; i
++ ) printf("%.2lf\n", a
[i
][n
+1]);}else if (t
== 1) puts("Infinite group solutions");else puts("No solution");return 0;
}
問題二:if (fabs(a[t][c]) < eps) continue;如何理解。
假設 c表示列,r表示行,此時我們進行到了 c=2 r=2
1 0 2 3
0 0 3 2
0 0 2 3
你會發現此時r行之下 的c列的絕對值最大值就是0.
說明此時的第c列已經化簡好了那么,那么我們就不需要在進行下面的化簡操作,
但是此時我們的第r行不用變,此時c加1 那么我們就接著從 第二行 第三列開始找絕對值最大的數。
如果我們的r向后移動了,那么此時我們的第2行是沒有化簡的,這顯然是不對的。
以此為例,r如果向后移動了,此時r=3,c=3 但是此時我們的 第二行 第三個數 是 3 并不是1 這種最簡的形態。
問題三:倒著推解是如何來的
當有唯一解的時候,我們最后的化簡一定是這種。
解的最終形式,如下所示:
我們倒著將每一行都簡成每一行只有一個1 的形式。 這里模擬一下,代碼就懂了。這里不在贅述。
最后,謝謝各位的觀看。我們下期再見!!!
總結
以上是生活随笔為你收集整理的高斯消元法讲解的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。