算法分析
高斯消元,是求解\(n\)个\(n\)元\(1\)次方程组的算法,一般情况下时间复杂度为\(O(n^3)\)。
我们把这\(n\)个方程组看成一个\(n\times (n+1)\)的矩阵。以样例为例:
\[ \left( \begin{matrix}
{{x}_{1}} & 3\times {{x}_{2}} & 4\times {{x}_{3}} \\
{{x}_{1}} & 4\times {{x}_{2}} & 7\times {{x}_{3}} \\
9\times {{x}_{1}} & 3\times {{x}_{2}} & 2\times {{x}_{3}} \\
\end{matrix} \right)=\left( \begin{matrix}
5 \\
3 \\
2 \\
\end{matrix} \right)
\]
我们把答案也写成矩阵的形式,不难发现:我们的目标矩阵应该形如下面
\[\left( \begin{matrix}
{{x}_{1}} & 0 & 0 \\
0 & {{x}_{2}} &0 \\
0& 0& {{x}_{3}} \\
\end{matrix} \right)=\left( \begin{matrix}
-\frac{37}{38} \\
\frac{197}{38} \\
-\frac{91}{38} \\
\end{matrix} \right)
\]
我们选择当前没有求解过的一个未知数(设为\(x_i\)),将\(x_i\)前的系数化为\(1\),然后用这样一行方程与其他方程相减相消,使得其他方程\(x_i\)前的系数都为\(0\).
考虑选取\(x_i\),一个最直观的想法是第\(i\)行选取的未知数是\(x_i\),但如果\(x_i=0\),显然就这个方程怎么转化都不会使\(x_i=1\),在这种情况下我们应选取\(x_i\)前系数不为\(0\)的一个方程,并与之交换。如果所有\(x_i\)的系数都是\(0\),那么\(x_i\)有无数解。
当出现\(0=a(a\ne 0)\)的情况,方程无解。
注意中间变量开double
型!
代码实现
#include<bits/stdc++.h>
using namespace std;
#define maxn 105
int n;
double a[maxn][maxn];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n+1;j++)scanf("%lf",&a[i][j]);
for(int i=1;i<=n;i++){
int p=0;
for(int j=i;j<=n;j++){if(a[j][i]!=0){p=j;break;}}
if(!p){puts("No Solution");return 0;}
for(int j=1;j<=n+1;j++)swap(a[i][j],a[p][j]);
double k=a[i][i];//错误笔记:中间变量使用int型
for(int j=1;j<=n+1;j++)a[i][j]/=k;
for(int j=1;j<=n;j++){
if(i==j)continue;
double kk=a[j][i];
for(int l=1;l<=n+1;l++)a[j][l]-=kk*a[i][l];
}
}
for(int i=1;i<=n;i++)printf("%.2lf\n",a[i][n+1]);
return 0;
}