[洛谷P3389][模板]高斯消元法

先貼一段百科ios

  數學上,高斯消元法,是線性代數規劃中的一個算法,可用來爲線性方程組求解。但其算法十分複雜,不經常使用於加減消元法,求出矩陣的秩,以及求出可逆方陣的逆矩陣。不過,若是有過百萬條等式時,這個算法會十分省時。一些極大的方程組一般會用迭代法以及花式消元來解決。當用於一個矩陣時,高斯消元法會產生出一個「行梯陣式」。高斯消元法能夠用在電腦中來解決數千條等式及未知數。算法

 

計算機實現高斯消元法其實利用了矩陣的性質,關於矩陣和行列式的性質見某度百科:spa

      行列式 https://baike.baidu.com/item/%E8%A1%8C%E5%88%97%E5%BC%8F code

      矩陣 https://baike.baidu.com/item/%E7%9F%A9%E9%98%B5/18069blog

 

對於方程來講,有:ci

1)兩方程互換,解不變;get

2)一方程乘以非零數k,解不變;數學

3)一方程乘以數k加上另外一方程,解不變it

 

根據這三項性質, 咱們可將方程中的各個未知數消去, 當方程個數和未知數總數相等時, 咱們能夠經過消元直接得出一個未知數的值, 這個方程必定是可解的.io

 

對應到行列式, 有行列式的如下性質:

1)對換行列式中兩行的位置,行列式反號

2)行列式的某一行乘任一非零數 k 等於用這個數乘此行列式

3)一行加上另外一行的k倍,行列式的值不變

 

根據這三條性質, 咱們必定能夠經過一系列流程將行列式轉化成一個上三角, 那麼也就有了在方程中各個未知數的值.

 

具體的操做流程

      1. 用一個非零的數乘矩陣的某一行

      2. 將一行的k倍加到另外一行上

      3. 交換矩陣中兩行的位置

 

其餘的代碼裏都寫註釋了

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 
 5 using namespace std;
 6 
 7 int n;
 8 double a[101][102];
 9 
10 void solve()
11 {
12     int g;
13     for(int i=1;i<=n;i++)//消元循環,i用於檢索對角線上各個點的行列
14     {
15         if(!a[i][i])
16         {
17             int r=i; //記錄當前所在的行
18             for(r=i+1;r<=n;r++) //尋找當前列上不爲零的一行
19                 if(a[r][i])
20                 {
21                     break;
22                 }
23             for(int j=1;j<=n+1;j++)
24                 swap(a[r][j],a[i][j]); //換行
25         }
26         /* 接下來利用高斯消元法求解
27         實際左下的三角形對整個式子的結果無影響,
28         只需根據它們求上下的比例關係 */
29         for(int k=i+1;k<=n;k++) //k用於記錄需消元的行 
30             for(int j=n+1;j>=i;j--) //j用於記錄該行每一個須要變化的,用於計算結果的係數
31                 {
32                     a[k][j] -= (a[k][i]/a[i][i])*a[i][j];
33                 }
34                 /*
35                    這裏是求出了這一行須要消去的係數和它上面對應的數的
36                    關係,而後按照這個關係對無需消去的數求差,這裏必定
37                    是按照三角形消的,由於最外層循環的i在改變,從而就改
38                    變了開始這一「消元」循環的位置,注意用雙精
39                 */
40     }
41 
42     for(int i=n;i>=1;i--) //求解循環,從最後一個解倒推
43     {
44         if(!a[i][i])
45         {
46             cout<<"No Solution";
47             return;
48         }
49         for(int j=i+1;j<=n;j++)
50             a[i][n+1] -= a[j][n+1]*a[i][j]; //將解存到等式右邊
51         a[i][n+1]/=a[i][i]; //最後的值除以當前的未知數的係數
52     }
53 
54     for(g=1;g<=n;g++)
55         printf("%.2lf\n",a[g][n+1]);
56 }
57 
58 int main()
59 {
60     int pl;
61     ios::sync_with_stdio(false);
62     cin>>n;
63     for(int i=1;i<=n;i++)
64         for(int j=1;j<=n+1;j++)
65             cin>>a[i][j];
66     solve();
67 
68     return 0;
69 }

在這裏感謝Moster_Yi神仙的耐心指導QwQ

相關文章
相關標籤/搜索