高斯消元法

sad_lin發表於2024-09-10

模板題

我寫不明白我要用其他人的學習筆記

其實也沒法寫,真要一步步寫很複雜。

無非就是依次將每個數減掉係數,最後成為一個單位矩陣。

所以看註釋:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+5;
int n;                      // n 表示方程的個數,即有 n 個變數
double a[104][104];          // a 是增廣矩陣,a[i][j] 表示第 i 行第 j 列的元素,矩陣大小為 n x (n+1)

int main(){
	ios::sync_with_stdio(false);  // 最佳化輸入輸出效率
	cin >> n;                      // 輸入變數的個數,即 n 階矩陣
	// 輸入增廣矩陣
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= n + 1; j++){
			cin >> a[i][j];         // 輸入每個係數和常數項(n x n 的係數矩陣加上 n 個常數項)
		}
	}
	// 高斯-約旦消元法
	for(int i = 1; i <= n; i++){
		int now = i;                // 當前正在處理的行(初始為第 i 行)

		// 尋找第 i 列的主元(即第 i 列第一個非 0 的元素)
		while(a[now][i] == 0 && now <= n){
			now++;                  // 如果當前行的 i 列為 0,則查詢下面的行
		}

		// 如果該列找不到非 0 的主元,則無解
		if(now == n + 1){
			cout << "No Solution";   // 輸出無解提示
			return 0;
		}

		// 交換當前行 i 和找到的主元所在的行 now
		for(int j = 1; j <= n + 1; j++){
			swap(a[i][j], a[now][j]); // 交換兩個行,確保 a[i][i] 非 0
		}

		// 將當前行的主元 a[i][i] 歸一化,令 a[i][i] = 1
		double pp = a[i][i];
		for(int j = 1; j <= n + 1; j++){
			a[i][j] = a[i][j] / pp;   // 將這一行所有元素除以 a[i][i]
		}

		// 對其他行進行消元,使得第 i 列的其餘行元素都為 0
		for(int j = 1; j <= n; j++){
			if(i != j){              // 跳過第 i 行本身
				double k = a[j][i];  // 消元係數
				for(int m = 1; m <= n + 1; m++){
					a[j][m] = a[j][m] - k * a[i][m]; // 消去 a[j][i],使其為 0
				}
			}
		}
	}

	// 輸出解
	for(int i = 1; i <= n; i++){
		printf("%.2lf\n", a[i][n+1]);  // 輸出解,保留兩位小數
	}
	return 0;
}

相關文章