[SDOI2006]线性方程组——高斯消元模板 大佬们的博客 Some Links

版权声明:欢迎大家转载,转载请标明出处。 https://blog.csdn.net/ylsoi/article/details/82933289

题目大意:

求解线性方程组。
判断惟一解,无穷解,无解的三种情况。

高斯消元:

洛谷的模板题好像怎么打都可以过,也没有具体区分无穷解和无解的情况,看来这个题才是高斯消元的真正模板。

惟一解:

这个大概是最好判断的了,在每次消元的时候都没有出现系数全部都为0的情况即整个线性方程组有惟一解。

无穷解和无解:

两种情况的判断稍微有一些麻烦,但是可以这样理解:如果一个线性方程在高消的过程中出现了某一列的系数全部为0,也就是出现了自由元,那么可以肯定一定不会存在惟一解。
那么剩下来的元和方程则构成了一组 {未知数<方程数} 的方程组,如果这个方程是有无穷解的,那么自由元任意取值的情况下,接下来的未知数都可以使这个方程数大于未知数的方程组恰好成立,同时其中必定有些方程之间线性相关,那么将最后一项系数消完之后,剩下来的系数为0的方程必定全部都是这种情况:
0 × x i = 0 0 × x n 1 = 0 0 × x n = 0 0\times x_{i}=0\\ \vdots \\ 0\times x_{n-1}=0\\ 0\times x_n=0
那么反过来,当存在自由元之后, {未知数<方程数} ,如果接来的方程不能恰好使得剩下来的未知数成立 ,那么将会是这种情况:
i n ,   0 × x i = a ( a ̸ = 0 ) \exists i\in n, \ 0\times x_i=a (a\not= 0)

于是我们只需要在存在了自由元之后,跳过这列未知数,然后接下来的未知数继续从这个方程开始消元,判断一下最后系数为0的方程的情况即可。
//本文纯属自己的拙见,如有错误,欢迎指正。

#include<bits/stdc++.h>

#define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
#define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
typedef long long ll;

using namespace std;

void File(){
    freopen("luogu2455.in","r",stdin);
    freopen("luogu2455.out","w",stdout);
}

template<typename T>void read(T &_){
    int __=0,mul=1; char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')mul=-1;
        ch=getchar();
    }
    while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
    _=__*mul;
}

const int maxn=100+10;
const double eps=1e-6;
int n,flag=1;
double a[maxn][maxn],ans[maxn];

void print(int id){
    printf("Matrix #%d\n",id);
    REP(i,1,(n+1)*5)putchar('-');
    putchar('\n');
    REP(i,1,n){
        REP(j,1,n+1)printf("%.2lf ",a[i][j]);
        putchar('\n');
    }
    REP(i,1,(n+1)*5)putchar('-');
    putchar('\n');
    putchar('\n');
}

void Gauss(){
    int p=1;
    REP(i,1,n){
        DREP(j,n,p+1)if(fabs(a[j][i])>fabs(a[j-1][i]))swap(a[j],a[j-1]);
        if(fabs(a[p][i])<eps)continue;
        REP(j,i+1,n+1)a[p][j]/=a[p][i]; a[p][i]=1;
        REP(j,p+1,n){
            REP(k,i+1,n+1)a[j][k]-=a[p][k]*a[j][i];
            a[j][i]=0;
        }
        ++p;
        //print(i);
    }
    if(p==n+1){
        DREP(i,n,1){
            ans[i]=a[i][n+1];
            REP(j,1,n-1)a[j][n+1]-=a[j][i]*ans[i];
        }
    }
    else{
        flag=0;
        REP(i,p,n)if(fabs(a[i][n+1])>eps)flag=-1;
    }
}

int main(){
//	File();
    read(n);
    REP(i,1,n)REP(j,1,n+1)read(a[i][j]);
    Gauss();
    if(flag==1)REP(i,1,n)printf("x%d=%.2lf\n",i,ans[i]);
    else printf("%d\n",flag);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ylsoi/article/details/82933289