首页 > 技术文章 > (模板)高斯消元法模板

FrankChen831X 2019-10-30 10:30 原文

题目链接:https://www.luogu.org/problem/P3389

题意:解方程数为n(<=100)的线性方程组的解。

思路:高斯消元法模板题,复杂度:O(n^3)。

AC代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;

const double eps=1e-8;
const int maxn=105;
int n;
double a[maxn][maxn],ans[maxn];

void Gauss(){
    for(int i=1;i<=n;++i){
        int r=i;
        for(int j=i+1;j<=n;++j)  //找主元系数绝对值最大的行
            if(fabs(a[j][i])>fabs(a[r][i]))
                r=j;
        if(fabs(a[r][i])<eps){   //最大为0时无解
            printf("No Solution\n");
            return;
        }
        if(r!=i) swap(a[i],a[r]);//交换
        double div=a[i][i];
        for(int j=i;j<=n+1;++j)  //系数化为1
            a[i][j]/=div;
        for(int j=i+1;j<=n;++j){ //消元
            div=a[j][i];
            for(int k=i;k<=n+1;++k)
                a[j][k]-=div*a[i][k];
        }
    }
    ans[n]=a[n][n+1];
    for(int i=n-1;i>=1;--i){     //回带
        ans[i]=a[i][n+1];
        for(int j=i+1;j<=n;++j)
            ans[i]-=a[i][j]*ans[j];
    }
    for(int i=1;i<=n;++i)
        printf("%.2f\n",ans[i]);
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n+1;++j)
            scanf("%lf",&a[i][j]);
    Gauss();
    return 0;
}

 

优化版本:

高斯-约旦消元法,相比与传统的高斯消元法,高斯-约旦消元法精度高、代码简单、没有回带过程。本质上与传统高斯消元法不同的是每选择一个主元,去消去其它方程的该变量时是将其它所有的方程都消去,而高斯消元法仅消去下面的方程,因此不需要回带。

AC代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;

const double eps=1e-8;
const int maxn=105;
int n;
double a[maxn][maxn];

void Gauss(){
    for(int i=1;i<=n;++i){
        int r=i;
        for(int j=i+1;j<=n;++j)  //找主元系数的绝对值最大的一行
            if(fabs(a[j][i])>fabs(a[r][i]))
                r=j;
        if(fabs(a[r][i])<eps){   //最大为0,无解
            printf("No Solution\n");
            return;
        }
        if(r!=i)
            for(int j=1;j<=n+1;++j)
                swap(a[i][j],a[r][j]);
        for(int j=1;j<=n;++j)    //消元
            if(j!=i){
                double tmp=a[j][i]/a[i][i];
                for(int k=i;k<=n+1;++k)
                    a[j][k]-=a[i][k]*tmp;
            }
    }
    for(int i=1;i<=n;++i)
        printf("%.2f\n",a[i][n+1]/a[i][i]);
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n+1;++j)
            scanf("%lf",&a[i][j]);
    Gauss();
    return 0;
}

 

推荐阅读