一、基本描述
1.高斯消元
主要用来求解线性方程组,也可以求解矩阵的秩,矩阵的逆。在ACM中是一个有力的数学武器。
时间复杂度是O(n3),主要与方程组的个数,未知数的个数有关。
2.什么是线性方程组?
有多个未知数,并且每个未知数的次数均为一次,这样多个未知数组成的方程组为线性方程组。
二、算法实现
高斯消元法就是手解方程组。
基本原理就是:消元(因为线性方程组次数为1次,不需要考虑降次),然后回代,在得到kx=b这类的式子后,就可以显而易见得到x的解了。
举例说明高斯消元法。
假设有如下的方程组:
写成矩阵形式就是: AX=B ,其中:
所以, 我们要以一定的策略, 对 A 和 B 施以一系列的初等变换, 当 A 化为单位矩阵的时候,B 就为方程组的解。
三、高斯消元法实现
网上很多模板还强调解出矩阵的上三角形,但是对于一般的题目来说,并没有必要。学会怎么解就好了。
直接例题上板子。
1.bzoj1013 [JSOI2008]球形空间产生器sphere
【题目大意】
给出n维空间中给出n+1个点的坐标,求出球心坐标。
【思路】
令球心坐标为x1,x2...xn,假设当前第i个点坐标为a1,a2...,an,第i+1个点坐标为b1,b2...,bn,则由半径相等可得:
(a1-x1)^2+(a2-x2)^2+...+(an-xn)^2=(b1-x1)^2+(b2-x2)^2+...+(bn-xn)^2
化简可得:
2(a1-b1)x1+2(a2-b2)x2+...+2(an-bn)xn=(a1^2+a2^2+...+an^2-b1^2-b2^2-...-b3^2)
如此可得到n个一元n次方程组,用最简单的高斯消元搞一搞就好了。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #define maxn 25 6 using namespace std; 7 const double eps=1e-6; 8 double f[maxn],a[maxn][maxn]; 9 int n; 10 void Gauss(){ 11 int i,j,now=1;//now表示处理到第几行 12 for (i=1;i<=n;i++){ //化简为行阶梯型 13 for (j=now;j<=n;j++){ 14 if (fabs(a[j][i])>eps) break; //当前未知量系数不为0 15 } 16 if (j>n) continue; 17 if (j!=now){ 18 for (int k=1;k<=n+1;k++) swap(a[j][k],a[now][k]); 19 } 20 double t=a[now][i]; 21 for (int k=1;k<=n+1;k++) a[now][k]/=t; 22 for (int k=1;k<=n;k++){ 23 if (k!=now){ 24 t=a[k][i]; 25 for (int l=1;l<=n+1;l++){ 26 a[k][l]-=t*a[now][l]; 27 } 28 } 29 } 30 now++; 31 } 32 return ; 33 } 34 int main(){ 35 double x; 36 scanf("%d",&n); 37 for (int i=1;i<=n;i++) scanf("%lf",&f[i]); 38 for (int i=1;i<=n;i++){ 39 for (int j=1;j<=n;j++){ 40 scanf("%lf",&x); 41 a[i][j]=2*(x-f[j]); 42 a[i][n+1]+=x*x-f[j]*f[j]; 43 } 44 } 45 Gauss(); 46 for (int i=1;i<n;i++) printf("%.3lf ",a[i][n+1]); 47 printf("%.3lf ",a[n][n+1]); 48 return 0; 49 }