AcWing 883. 高斯消元解线性方程组(高斯消元模板)
先出裸的模板:
#include<bits/stdc++.h>using namespace std; const int N = 110; typedef double db; db a[N][N]; const db eps = 1e-8; int n;int gauss() {int c,r;for(c=0,r=0;c<n;++c)/***************/{int t = r;for(int i=r+1;i<n;++i) if(fabs(a[i][c])>fabs(a[r][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;i>=c;--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;j>=c;--j){a[i][j]-=a[r][j]*a[i][c];/******************/}}}++r;}if(r<n){for(int i=r;i<n;++i) if(fabs(a[i][n])>eps) return 1;/*****************/return 2;}/********************/for(int i=n-1;i>=0;--i){for(int j=i+1;j<n;++j){a[i][n]-=a[i][j]*a[j][n];}}return 0; }int main() {cin>>n;for(int i=0;i<n;++i){for(int j=0;j<n+1;++j){cin>>a[i][j];}}int t = gauss();if(t==2){cout<<"Infinite group solutions"<<endl;}else if(t==1) cout<<"No solution"<<endl;else{for(int i=0;i<n;++i){if(fabs(a[i][n])<eps) a[i][n]=0;/******************/printf("%.2lf\n",a[i][n]);}}return 0; }輸入一個包含 n 個方程 n 個未知數的線性方程組。
方程組中的系數為實數。
求解這個方程組。
下圖為一個包含 m 個方程 n 個未知數的線性方程組示例:
輸入格式
第一行包含整數 n。
接下來 n 行,每行包含 n+1 個實數,表示一個方程的 n 個系數以及等號右側的常數。
輸出格式
如果給定線性方程組存在唯一解,則輸出共 n 行,其中第 i 行輸出第 i 個未知數的解,結果保留兩位小數。
如果給定線性方程組存在無數解,則輸出 Infinite group solutions。
如果給定線性方程組無解,則輸出 No solution。
數據范圍
1≤n≤100,
所有輸入系數以及常數均保留兩位小數,絕對值均不超過 100。
輸入樣例:
3
1.00 2.00 -1.00 -6.00
2.00 1.00 -3.00 -9.00
-1.00 -1.00 2.00 7.00
輸出樣例:
1.00
-2.00
3.00
初等行列變化:
1.某一行乘上一個非零數,矩陣不變
2.某一行乘上一個常數加到另一行上,矩陣不變
3.交換矩陣中某兩行的元素,矩陣不變
思路:利用初等行列變化初等行列變化將矩陣變換成上三角形矩陣,再由后往前推出解
上三角形矩陣帶來的結果有三種:無解,有唯一解,無窮多解
①無解:若在最后化成的上三角形矩陣中,正對角線中某個元素為0,但其所在行的最后一列元素不為0時,此時矩陣無解
②有無數解:若在最后化成的上三角形矩陣中,存在正對角線中某個元素為0,且其所在行的最后一列元素也為0時,此時矩陣有無窮組解
③有唯一解:若在最后化成的上三角形矩陣中,不存在正對角線中某個元素為0,此時矩陣有唯一解
算法步驟
1.枚舉每一列c,找到當前列絕對值最大的一行
2.用初等行變換(2) 把絕對值最大的這一行換到最上面(注意:“最上面”指的是未確定階梯型的行,而不是第一行)
3.用初等行變換(1) 將該行的第一個數變成 1 (其余所有的數字依次跟著變化)
4.用初等行變換(3) 將下面所有行的當前列的值變成 0
對于行的元素改變操作,總是按列倒序遍歷 #include<bits/stdc++.h>using namespace std; typedef double db; const int N = 110; /* C++浮點數存在誤差,不能直接判斷0,要判斷是否小于一個很小的數,如果小于這個很小的數,就認為是0,如小于1e-6*/ const db eps = 1e-8;int n; db a[N][N];int gauss()// 高斯消元,答案存于a[i][n]中,0 <= i < n {int c,r;for(c = 0,r = 0;c < n; ++c)//上界是小于n,因為是枚舉系數矩陣的列{int t = r;// ① 找到當前這一列中絕對值最大的一行for(int i = r; i < n; ++i){if(fabs(a[i][c])>fabs(a[t][c])) t = i;}// 如果這一列中最大值已經是0了,直接continue進入下一列if(fabs(a[t][c])<eps) continue;//剪枝// ② 將這行換到最上面for(int i = c; i <= n; ++i) swap(a[t][i],a[r][i]);// 將絕對值最大的行換到最頂端// ③ 將該行第一個數變成1// 將r行中c列后的每一個元素除上一個a[r][c](該行的第一個不為零的元素)for(int i = n; i >= c; --i) a[r][i]/=a[r][c];// 將當前行的首位變成1for(int i = r+1; i < n; ++i)// 用當前行將下面所有的列消成0{if(fabs(a[i][c])>eps)//剪枝{for(int j = n; j >= c; --j){// a[r][j]當前這行的第j列元素,a[i][c]是下面行的最前面的元素//目的是把第r+1行~n行的第c列元素都消除為0a[i][j] -= a[r][j] * a[i][c];//聯想學線代怎么做的就行}}}++r;}if(r<n)// 無解和無窮多解的判斷{// 如果出現了等號左右一個為0一個非0,則說明無解for(int i = r; i < n; ++i)if(fabs(a[i][n])>eps) return 2;// 無解// 否則說明有無窮多解return 1;// 有無窮多組解}// 回溯計算每個值xifor(int i = n-1; i >= 0; --i)for(int j = i+1; j < n; ++j)a[i][n] -= a[i][j] * a[j][n]; //a[j][n]即代表之前循環已經求出來的未知數xj,a[i][j]代表當前枚舉到的第i行中xj的系數,簡單解個方程就行return 0;// 有唯一解 }int main() {cin>>n;// 存儲線性方程組的增廣矩陣for(int i=0;i<n;++i){for(int j=0;j<n+1;++j){cin>>a[i][j];}}int t = gauss();// 執行高斯消元if(t==2) cout<<"No solution"<<endl;// 否則無解else if(t==1) cout<<"Infinite group solutions"<<endl;// 如果 t = 1,線性方程組存在無數解else{for(int i=0;i<n;++i){if(fabs(a[i][n])<eps) a[i][n] = 0;// 去掉輸出 -0.00 的情況printf("%.2lf\n",a[i][n]);// %.2lf 保留兩位小數}}return 0; }總結
以上是生活随笔為你收集整理的AcWing 883. 高斯消元解线性方程组(高斯消元模板)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 云服务器与实体服务器性能,实体服务器和云
- 下一篇: 苹果手机变成耳机模式怎么调回来_百元真无