高斯消元法
高斯消元法
可以用于求解线性方程组,即n元1次方程组。利用矩阵,大致思路与普通解方程方法类似。只是更具一般性。将系数与右侧的常数存成一个矩阵,然后每次用第i行消去下面每行的第i个系数,最后就会得到一个一元方程,然后从后到前依次代回即可。
然后就是精度的问题,因为计算机中没有分数,所以只能用double来存,但是double的精度也是有限的,所以要想办法维护精度。
第一种优化办法就是在用第i行去消第i个系数时,从下面所有行中选择第i个系数的绝对值最大的一个与当前行交换,这样可以使每次消元时差距尽量大,然后就可以保持精度了。
第二种优化就是在进行消元时,不是用一个变量来储存两行首元素的商,而是每次直接计算。这样就必须防止第一行提前被修改,所以倒着进行修改。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cmath> 5 using namespace std; 6 const int N=110,M=1010; 7 int n,m; 8 double a[N][N],tmp[N][N],ans[N]; 9 inline void work() 10 { 11 for(int i=1;i<=n;++i) 12 { 13 int kk=i; 14 for(int j=i+1;j<=n;++j) 15 if(abs(a[kk][i])<abs(a[j][i])) 16 kk=j; 17 if(kk!=i) 18 for(int j=1;j<=n+1;++j) 19 swap(a[kk][j],a[i][j]); 20 for(int j=i+1;j<=n;++j) 21 { 22 for(int k=n+1;k>=i;--k) 23 a[j][k]=a[j][k]-a[j][i]/a[i][i]*a[i][k]; 24 } 25 } 26 27 for(int i=n;i>=1;--i) 28 { 29 for(int j=n;j>i;--j) 30 { 31 a[i][j]*=ans[j]; 32 a[i][n+1]-=a[i][j]; 33 } 34 ans[i]=a[i][n+1]/a[i][i]; 35 } 36 } 37 int main() 38 { 39 scanf("%d%d",&n,&m); 40 for(int i=1;i<=n;++i) 41 for(int j=1;j<=n;++j) 42 scanf("%lf",&tmp[i][j]); 43 for(int k=1;k<=m;++k) 44 { 45 memset(ans,0,sizeof(ans)); 46 memset(a,0,sizeof(a)); 47 for(int i=1;i<=n;++i) 48 for(int j=1;j<=n;++j) 49 a[i][j]=tmp[i][j]; 50 for(int j=1;j<=n;++j) 51 scanf("%lf",&a[j][n+1]); 52 work(); 53 for(int i=1;i<=n;++i) 54 printf("%.9llf ",ans[i]); 55 printf("\n"); 56 } 57 return 0; 58 }