P3389 【模板】高斯消元法
把所有方程放到一个二维数组里
样例的数组为[ 1,3,4,5 ]
[ 1,4,7,3 ]
[ 9,3,2,2 ]
考虑一个一个消元
拿一个方程出来,把未知数 x 的系数化成1
用加减消元消去其他方程的 x
然后再消下一个未知数
最后一个未知数消完后再把值往上一个方程代入
最后每个未知数都求出来了
如果消 x 的时候发现所有方程的 x 的系数都是 0
那么 x 可以取任何值,就是有多个解
判一下就好了
拿方程时优先拿系数大的可以减小误差(不会证明)
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const double eps=1e-7; double mp[107][107],ans[107]; int n; inline void slove() { for(int i=1;i<=n;i++)//消去第i位未知数 { double mx=mp[i][i]; int pos=i; for(int j=i+1;j<=n;j++)//注意前面的方程用过了不能再用 if(fabs(mx)<fabs(mp[j][i])) mx=mp[j][i],pos=j; swap(mp[i],mp[pos]);//找系数最大的方程 if(fabs(mp[i][i])<eps)//判一下多解的情况 { cout<<"No Solution"; exit(0); } double div=mp[i][i]; for(int j=i;j<=n+1;j++) mp[i][j]/=div;//把此方程未知数的系数化为1 for(int j=i+1;j<=n;j++) { div=mp[j][i]; for(int k=i;k<=n+1;k++) mp[j][k]-=mp[i][k]*div;//用加减消元消去其他方程的此未知数 } } for(int i=n;i;i--) { ans[i]=mp[i][n+1]; for(int j=i+1;j<=n;j++) ans[i]-=mp[i][j]*ans[j];//把后面的答案往前带 } } int main() { cin>>n; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) scanf("%lf",&mp[i][j]); scanf("%lf",&mp[i][n+1]); } slove(); for(int i=1;i<=n;i++) printf("%.2lf\n",ans[i]); return 0; }