【模板】高斯消元

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/82766272

参考题目:洛谷P3389


#解析:

首先高斯消元是干什么的?

求解如下形式的线性方程组 i = 1 , 2 , 3... n 对于\forall i=1,2,3...n j = 1 n a i , j x j = b i \sum_{j=1}^{n} a_{i,j}*x_j = b_i

那么现在我们考虑把原来的方程转化成如下的 n ( n + 1 ) n*(n+1) 矩阵
a 1 , 1 , a 1 , 2 . . . a 1 , n , b 1 a_{1,1},a_{1,2}...a_{1,n},b_1 a 2 , 1 , a 2 , 2 . . . a 2 , n , b 2 a_{2,1},a_{2,2}...a_{2,n},b_2 . . .   . . . ...\text { }... a n , 1 , a n , 2 . . . a n , n , b n a_{n,1},a_{n,2}...a_{n,n},b_n

考虑将前面的矩阵(前 n n n*n 的部分)消成每行每列只有一个元素不为0,那么不为零的那个列所对应的未知数就是方程的解。

第一份代码是回代版的高斯消元。
考虑将矩阵消元成一个上三角矩阵,就是只有上三角的元素非0,那么最后一行可以直接得出最后一个元素的解,然后再利用这个解将这一列所有的该元素系数全部消成0。

第二份代码是不用回代的高斯消元。
就是直接利用这一行的非0元将该列所有系数全部消为0, w w 记录该行保留的是第几个数。

对于方程无解的情况(仔细想一想,不存在的),或者有无穷多解的情况。

当某一列在消元过程中全部为0时,即在该列没有任何系数,那么这个元素可以取任意值,即方程有无数组解,直接退出,防止除以0引发错误。


代码1:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline
ll getint(){
    re ll num=0;
    re char c;
    re bool f=1;
    while(!isdigit(c=gc()))if(c=='-')f=0;
    while(isdigit(c))num=(num<<1)+(num<<3)+(c^48),c=gc();
    return f?num:-num;
}

double a[102][102];
int n;

inline
bool gauss(){
	for(int re i=1;i<=n;++i){
		int pos=i;
		for(int re j=i;j<=n;++j){
			if(fabs(a[j][i])-fabs(a[pos][i])>=1e-6)pos=j;
		}
		if(i!=pos)swap(a[i],a[pos]);
		if(fabs(a[i][i])<1e-6)return false;
		for(int re j=i+1;j<=n+1;++j)a[i][j]/=a[i][i];
		a[i][i]=1;
		for(int re j=i+1;j<=n;++j){
			double tmp=a[j][i];
			for(int re k=i;k<=n+1;++k)
			a[j][k]-=a[i][k]*tmp;
		}
	}
	return true;
}

signed main(){
	n=getint();
	for(int re i=1;i<=n;++i)
	for(int re j=1;j<=n+1;++j)
	a[i][j]=getint();
	if(!gauss()){
		puts("No Solution");
	}
	else{
		for(int re i=n-1;i;--i){
			for(int re j=i+1;j<=n;++j)
			a[i][n+1]-=a[i][j]*a[j][n+1],a[i][j]=0;
		}
		for(int re i=1;i<=n;++i){
			printf("%.2f\n",a[i][n+1]);
		}
	}
	return 0;
} 

代码2:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline
ll getint(){
    re ll num=0;
    re char c;
    re bool f=1;
    while(!isdigit(c=gc()))if(c=='-')f=0;
    while(isdigit(c))num=(num<<1)+(num<<3)+(c^48),c=gc();
    return f?num:-num;
}

double a[102][102];
int w[101];
double x[101];
int n;

inline
bool gauss(){
    for(int re i=1;i<=n;++i){
        int pos=-1;
        double maxn=0.0;
        for(int re j=1;j<=n;++j){
            if(fabs(a[i][j])-1e-6>maxn)
            maxn=fabs(a[i][j]),pos=j;
        }
        if(pos==-1)return false;
        w[i]=pos;
        for(int re j=1;j<=n;++j){
            if(i!=j){
                double tmp=a[j][pos]/a[i][pos];
                for(int re k=1;k<=n+1;++k)a[j][k]-=a[i][k]*tmp;
            }
        }
    }
    return true;
} 

int main(){
    n=getint();
    for(int re i=1;i<=n;++i)
    for(int re j=1;j<=n+1;++j)
    a[i][j]=getint();
    if(!gauss()){
        puts("No Solution");
    }
    else {
        for(int re i=1;i<=n;++i)x[w[i]]=a[i][n+1]/a[i][w[i]];
        for(int re i=1;i<=n;++i)printf("%.2f\n",x[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/82766272