【アルゴリズム】ガウスエリミネーションの詳細説明

元のリンク(アムウェイを強く推奨)

0.前提知識

  • 3 つの変数で連立一次方程式を解く方法を理解する
  • 手もあれば頭脳もある

1.回答の表示と保管

まず連立方程式を解きます。

2x+3y+5z=31
x-4y -z=-6
4x+2y-5z=9


この方程式系を、機械が読み取れるテーブル形式に書き込みます。

2 3 5 31
1 -4 -1 -6
4 2 -5 9

最初の列はxxを表しますxの係数、2 列目はyyyの係数...追加の 4 列目は、答えの特定の値であることに
注意してください最初の行は式 1 を表し、2 列目は式 2 を表します...


常にx、y、zx、y、zを使用するため× zはnnを意味します数値nは不便なので、a 1 、 a 2 . . . a_1,a_2...a_n をある1ある2ある表現します。

つまり、上の表の意味は次のとおりです。

i ( 1 ≤ i ≤ n ) i(1\le i\le n)( 1列n ) は各式のai a_iある私はn + 1係数n+1n+列1は、各式の特定の値(保存時は通常の値であるため、閲覧者は明確に区別する必要があります)

i ( 1 ≤ i ≤ n ) i(1\le i\le n)( 1行n )はii 番目を表します私は数式。

次に、テキスト全体で、[ i ] [ j ] a[i][j]を使用します。a[i][j] 表示第 i i i、 jj列jの値/係数


2. ガウス消去法の考え方

名前はとても高級ですが、やり方は非常に雑です。具体的な演算は、加算、減算、消去 + 置換、消去です。

まず、上記の係数行列に従います。

2 3 5 31
1 -4 -1 -6
4 2 -5 9

次に、ガウス消去法を開始します。

列挙ii _i未知のものを順番に削除します ai a_iある私は

次にjjを列挙しますj0 0ではない最小絶対値0a [ j ] [ i ] a[j][i]a [ j ] [ i ]

最小値a[j][i]a[j][i]を見つける[ j ] [ i ]jj _jの後に jj番目を追加しますj式とii表情交換

列挙型jjj,设mul = a [ i ] [ i ] / a [ j ] [ i ] mul=a[i][i]/a[j][i]ムル_ _=a [ i ] [ i ] / a [ j ] [ i ]
jjj式にmul mulマルマイナスii _私は

なぜこれをレイヤーごとに行うのかを分析してみましょう。
まず、iiを列挙します。i ii を削除する番号がわかりませ
次に、jjj 使得 a [ j ] [ i ] a[j][i] a [ j ] [ i ]が最小ですが、実際には必要ありません(理由は後で説明します)。交換jjjの式とii私は式です。
後で、各jjjjjj 式子乘上 a [ i ] [ i ] / a [ j ] [ i ] a[i][i]/a[j][i] a [ i ] [ i ] / a [ j ] [ i ] jj は次のようにする必要があるjii項iの係数はii調整されますi 式子第 i i i項の係数は同じです。jj
変更しますjマイナスii式iの目的は、 ii を消去する項目iの係数

0 0ではなく最小の絶対値を選択する理由0 a [ j ] [ i ] a[j][i][ j ] [ i ]jj _jはどこですか?なぜなら、絶対値が最小の[ j ] [ i ] a[j][i]a [ j ] [ i ] は 、より分割可能な状況を大まかに形成ため、精度の低下を避けることができます0 0は取れません
0は当然です。

それでも理解できない場合は? 次に、レイヤーごとにシミュレーションします。
この方程式系を例として見てみましょう。

2 3 5 31
1 -4 -1 -6
4 2 -5 9

まず、最初の係数を削除します。

1 -4 -1 -6
2 3 5 31
4 2 -5 9

最小値を求めますa [ 1 ] a[1]式a [ 1 ]については、最初の式に合わせて調整します。

1 -4 -1 -6
1 3/2 5/2 31/2
4 2 -5 9

2 番目の柿× 0.5 \times 0.5× 0 5

1 -4 -1 -6
0 11/2 7/2 43/2
4 2 -5 9

2 番目の式から最初の式を減算します。


類推すると、最終的な答えの係数行列は次のようになります: (整列しておらず、少し見苦しい)

4 0 0 20
0 -4.5 0 -9
0 0 7.611 22.833

そして最後のn + 1 n+1n+1係数をiii 行第 i i 列iの値で

3. 見たいコード。

P3389 [テンプレート] ガウス消去法

コメントは少し少ないですが、理解できます。

#include<bits/stdc++.h>
#define RI register int
using namespace std;typedef long long LL;const int inf=1073741823;int FL,CH;template<typename T>void in(T&a){
    
    for(a=0,FL=1,CH=getchar();!isdigit(CH);CH=getchar())FL=(CH=='-')?-1:1;for(;isdigit(CH);CH=getchar())a=a*10+CH-'0';a*=FL;}template<typename T,typename ...Args>void in(T&a,Args&...args){
    
    in(a);in(args...);}
const int maxn=110;const double eps=1e-6;
double a[maxn][maxn];
int n;
int main()
{
    
    
	cin>>n;
	for(RI i=1;i<=n;++i){
    
    
		for(RI j=1;j<=n+1;++j)scanf("%lf",&a[i][j]);}
	//输入系数矩阵
	for(RI rp,i=1;i<=n;++i)
	{
    
    
		rp=i;
		for(RI j=i+1;j<=n;++j)
		if(fabs(a[j][i])>fabs(a[rp][i]))rp=j;
		if(fabs(a[rp][i])<=eps)
		return printf("No Solution"),0;
		//寻找绝对值最小的 j
		//这个特殊一点,要判无解
		if(i!=rp)swap(a[rp],a[i]);
		//交换 j 和 i
		double div=a[i][i];
		for(RI j=1;j<=n;++j)
		if(j!=i){
    
    
			div=a[j][i]/a[i][i];
			//计算 mul 值
			for(RI k=1;k<=n+1;++k)
				a[j][k]-=a[i][k]*div;
			//乘上,再减去
			//高斯消元算法的精髓
		}
	}
	for(RI i=1;i<=n;++i)
		printf("%.2lf\n",a[i][n+1]/a[i][i]);//回代,并输出答案
	return 0;
}

おすすめ

転載: blog.csdn.net/zhy_Learn/article/details/118769379