P3389 【模板】高斯消元法
原题链接
题目大意
给定一个线性方程组,对其求解。
\(\texttt{Example Explain}\)
样例所示的方程组为:
\[\begin{cases}
x+3y+4z=5&(1)\\
x+4y+7z=3&(2)\\
9x+3y+2z=2&(3)\\
\end{cases}
\]
解题思路
高斯消元法的基本解题思路就是把其中的一个未知数先 系数化为一,然后再用这个未知数 消掉其他方程内的这个未知数,最后得出结果。
没看懂?用样例来解释一下。
首先把 \(x\) 系数化为一,\((1)\) 方程已经做到了。
然后用 \((2)-(1)\),把 \((2)\) 中的 \(x\) 消掉,再用 \((3)-9\times (1)\),把 \((3)\) 中的 \(x\) 消掉,最后方程式变成:
\[\begin{cases}
x+3y+4z=5&(1)\\
y+3z=-2&(2)\\
-24y-34z=-43&(3)\\
\end{cases}
\]
然后再把 \(y\) 系数化为一,此时就不能用到上面的 \((1)\) 了,因为会导致 \(x\) 的出现。而这个工作也已经完成了。
然后用 \((1)-3\times (2)\ ,\ (3)-(-24)\times(2)\) 得到:
\[\begin{cases}
x-5z=11&(1)\\
y+3z=-2&(2)\\
38z=-91&(3)\\
\end{cases}
\]
最后,就是解最后一个 \(z\) 了。首先,系数化为一,\((3)\) 变为 \(z=-\frac{91}{38}\),然后再把其他两个方程中的 \(z\) 去掉,变为:
\[\begin{cases}
x=-\frac{37}{38}&(1)\\[3pt]
y=\frac{197}{38}&(2)\\[3pt]
z=-\frac{91}{38}&(3)\\
\end{cases}
\]
保留两位小数后就是:
\[\begin{cases}
x=-0.97&(1)\\
y=5.18&(2)\\
z=-2.39&(3)\\
\end{cases}
\]
和样例一样。
随后,就可以把这个推出有 \(n\) 个方程的结果。
而有多数解只有一种可能,就是该方程中没有此未知数,即未知数为 \(0\)。
上代码
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
double a[110][110];
int n;
void print2DMatrix()
{
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n+1; j++)
printf("%0.2lf ",a[i][j]);
printf("\n");
}
printf("\n");
return;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
/* Code */
cin>>n;
for(int i=1; i<=n; i++)
for(int j=1; j<=n+1; j++)
cin>>a[i][j];
for(int i=1; i<=n; i++)
{
int maxpos=i;
for(int j=i+1; j<=n; j++)
if(a[j][i]>a[maxpos][i])
maxpos=j;
for(int j=1; j<=n+1; j++)
swap(a[i][j],a[maxpos][j]);
// print2DMatrix();
double temp=a[i][i];
if(temp==0)
{
cout<<"No Solution"<<endl;
return 0;
}
for(int j=1; j<=n+1; j++)
a[i][j]/=temp;
for(int j=1; j<=n; j++)
{
if(j==i)
continue;
temp=a[j][i];
for(int k=1; k<=n+1; k++)
a[j][k]-=temp*a[i][k];
}
// print2DMatrix();
}
for(int i=1; i<=n; i++)
printf("%0.2lf\n",a[i][n+1]);
return 0;
}