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