高斯消元初步

概述

高斯消元是线性代数中的一个算法,可以用来为线性方程组求解。

基本步骤

  1. 构造原矩阵为三角形格式

    [a[1][1] * x[1] + a[1][2] * x[2] + ... + a[1][n] * x[n] = y'[1]\ 0 * x[1] + a[2][2] * x[2] + ... + a[2][n] * x[n] = y'[2]\ 0 * x[1] + 0 * x[2] + ... + a[3][n] * x[n] = y'[3]\ ...\ 0 * x[1] + 0 * x[2] + ... + a[n][n] * x[n] = y'[n]\ 0 * x[1] + 0 * x[2] + ... + 0 * x[n] = y'[n + 1]\ ...\ 0 * x[1] + 0 * x[2] + ... + 0 * x[n] = y'[m]\ ]

  2. 从第n行开始逆推,一步一步将(a[i][j](i<j))也变换为0。

    因为第n行为(a[n][n] * x[n] = y'[n]),则(x[n] = y'[n] / a[n][n])

    第n-1行为(a[n-1][n-1] * x[n - 1] + a[n][n] * x[n] = y'[n - 1])。我们将得到的(x[n])代入,即可计算出(x[n-1])

    同样的依次类推就可以得到所有的(x[1]..x[n])

  3. 关于多解和无解的判定

    **无解: **当在求出的上三角矩阵中出现了 (a[i][1] = a[i][2] = ... = a[i][n] = 0), 但是(y'[i] != 0)时,产生了矛盾,即出现了无解的情况。

    **多解: **当等式两边出现(0*X[i]=0)时,显然(X[i])可以取无穷多个值,此时多解。

代码模板

#include<bits/stdc++.h>
#define M 505
#define db double 
using namespace std;
int n,m;
db A[M<<1][M],ans[M];
const db eps=1e-7;
void Swap(int i,int j){
	for(int k=1;k<=n+1;k++)
		swap(A[i][k],A[j][k]);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
		for(int j=1;j<=n+1;j++)
			scanf("%lf",&A[i][j]);
	for(int i=1;i<=n;i++){
		int id=i;
		for(int j=i+1;j<=m;j++)//找到最大的绝对值,保证精度
			if(abs(A[id][i])<abs(A[j][i]))
				id=j;
		if(id!=i)Swap(id,i);
		if(abs(A[i][i])<eps)return puts("Many solutions"),0;
		db div=A[i][i];
		for(int j=i;j<=n+1;j++)A[i][j]/=div;//一次构造三角形格式
		for(int j=i+1;j<=m;j++){
			for(int q=i+1;q<=n+1;q++)
				A[j][q]-=A[i][q]*A[j][i];
			A[j][i]=0;
		}
	}
	for(int i=1;i<=m;i++)//判断是否无解
		if(abs(A[i][n+1])>eps){
			bool flag=0;
			for(int j=1;j<=n&&!flag;j++)
				if(abs(A[i][j])>eps)flag=1;	
			if(!flag)return puts("No solutions"),0;
		}
	for(int i=n;i>=1;i--){//回带
		db val=A[i][n+1];
		for(int j=n;j>i;j--)
			val-=ans[j]*A[i][j];
		ans[i]=val/A[i][i];
	} 
	for(int i=1;i<=n;i++)printf("%d
",(int)(ans[i]+0.5));
	return 0; 
} 
原文地址:https://www.cnblogs.com/zryabc/p/10363873.html