即对增广矩阵进行初等行变换,将其转换为行最简阶梯形矩阵

AX = B与C(标准型)X = D是同解方程组。

来看算法实现过程:

有矩阵我们来进行初等行变换

一、先来枚举每一列:

①枚举第一列

1.找到第一列中绝对值最大的一行,这里即2 1 -3 -9这行

2.将绝对值最大的一行与第一行交换得到

3.将第一行第一个数变为1,得到

4.将下面所有行的第一列消成0,得到

这时候第一行已经固定了,所以接下来我们要从第二行开始的其他不固定的方程中寻找到第c列中绝对值最大的行。

 

②枚举第二列

1.找到第二列中绝对值最大的一行(注意此时第一行已经固定,因此我们只能从第二行开始寻找)即0 3/2 1/2 -3/2这行

2.将绝对值最大的一行与第二行交换得到

3.将第二行的第二个数变为1,得到

4.将第二行之下所有行的第二列消成0,得到

这时候第二行已经固定。

 

③枚举第三列

这里简化过程得到的结果是

 

二、将每行首非零元所在列的其他元素化为0

得到的是

 

代码实现即模拟手动进行初等行变换将矩阵化为行最简阶梯形矩阵

 

Acwing883 模板详解

#include<cstdio>
#include<cmath>
#include<algorithm>

using namespace std;

const int N = 110;
const double eps = 1e-6;

double a[N][N];
int n;

//debug
void out()
{
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n + 1; j++)
            printf("%5.2lf ", a[i][j]);
    
        printf("\n");
    }
    
    printf("\n\n");
}

int gauss()
{
    /****************************************************************************************************
    具体实现:
    1.枚举列,找到每列最大的绝对值,将其置换到当前未固定的最小行,然后将最小行之下的所有该列元素全部换为0
    2.如果有唯一解,那么再按照从最高行的位置将每一个解求解出来。
    ****************************************************************************************************/
    
    int r, c; //r为行,c为列
    for(c = 1, r = 1; c <= n; c++){
        int t = r; //初始化每次未固定的最小行为r
        for(int i = r + 1; i <= n; i++)
            if(fabs(a[i][c]) > fabs(a[t][c]))
                t = i;
        
        //如果这一列都为0,那么根据矩阵变换就无需进行这次的之后的操作了    
        if(fabs(a[t][c]) < eps) continue;
        
        //如果最小行不是初始化的值
        if(t != r){
            for(int j = 1; j <= n + 1; j++) swap(a[t][j], a[r][j]);
        }
        //交换后将其变为1
        for(int j = n + 1; j >= c; j--) a[r][j] /= a[r][c];
        
        //把最小行之下的所有该列元素都置为0,同时置为0的列元素所在行的元素也要改变
        for(int i = r + 1; i <= n; i++){
            if(fabs(a[i][c]) > eps)
                for(int j = n + 1; j >= c; j--)
                    a[i][j] = a[i][j] - a[i][c] * a[r][j];
        }
        r++;
    }
    
    if(r < n + 1){
        //由于r < n,所以可知至少有一个解是0x=0,故右边必须是0,否则就是无解
        for(int i = r; i <= n; i++) 
            if(fabs(a[i][n + 1]) > eps)
                return 2;
        return 1;
    }
    
    //当是唯一解时,我们需要将每个解都求解出来,因此我们需要从最后一个解开始,逐个借助已求出的解来解出其他的解
    //由于最后一个解本就确定了,故我们从倒数第二个开始解
    for(int i = n; i >= 1; i--){
        //每次是从该元素的后一个元素开始解
        for(int j = i + 1; j <= n; j++)
            a[i][n + 1] = a[i][n + 1] - a[i][j] * a[j][n + 1];
    }
    
    return 0;
}

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]);
            
    int t = gauss();
    
    //0代表唯一解,1代表无穷多组解,2代表无解
    if(t == 0){
        for(int i = 1; i <= n; i++) printf("%.2lf\n", a[i][n + 1]);
    }
    else if(t == 1) puts("Infinite group solutions");
    else puts("No solution");
    
    return 0;
}