高斯若尔当消元法

算法内容:

该算法主要用于求解线性方程组的解,其原理是,将增广矩阵化成行最简形矩阵,最终能求出方程是否有解、有解时自由元的个数和非自由元的解。

///
///                            _ooOoo_
///                           o8888888o
///                           88" . "88
///                           (| -_- |)
///                           O\  =  /O
///                        ____/`---'\____
///                      .'  \\|     |//  `.
///                     /  \\|||  :  |||//  \
///                    /  _||||| -:- |||||-  \
///                    |   | \\\  -  /// |   |
///                    | \_|  ''\---/''  |   |
///                    \  .-\__  `-`  ___/-. /
///                  ___`. .'  /--.--\  `. . __
///               ."" '<  `.___\_<|>_/___.'  >'"".
///              | | :  `- \`.;`\ _ /`;.`/ - ` : | |
///              \  \ `-.   \_ __\ /__ _/   .-` /  /
///         ======`-.____`-.___\_____/___.-`____.-'======
///                            `=---='
///        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
///                      Buddha Bless, No Bug !
///
#include <iostream>
#include <string>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#define eps 1e-9
using namespace std;
const int MAXN = 220;
double a[MAXN][MAXN], x[MAXN];///方程左边的矩阵和等于等式右边的值,求解之后X存的就是结果
int equ, var;///(方程数)和(未知数个数)
/*
返回-1表示一个解,0表示无解,其余的数表示有K个自由元
*/
int Gauss()
{
    int i, j, k, col, max_r;
    for (k = 0, col = 0; k < equ && col < var; k++, col++)
    {
        max_r = k;
        for (i = k + 1; i < equ; i++)///逐层寻找绝对值比第(k, k)个数大的数,便于后面化成行最简型
        {
            if (fabs(a[i][col]) > fabs(a[max_r][col]))///逐层寻找绝对值比第(k, k)个数大的数,便于后面化成行最简型
            {
                max_r = i;
            }
        }
        if (abs(a[max_r][col]) < eps)
        {
            continue;
        }
        if (k != max_r)///如果最大的数所在行不与K同行,就进行交换,方便后面的行减去他,然后转换成行最简型
        {
            for (j = col; j < var; j++)///进行交换
            {
                swap(a[k][j], a[max_r][j]);
            }
            swap(x[k], x[max_r]);
        }
        x[k] /= a[k][col];
        for (j = col + 1; j < var; j++)///使(k,col)元素在k行以后的元素都除以他,而他自己变成1
        {
            a[k][j] /= a[k][col];///使a[k][col] = 1,使这行逐渐变成行最简形矩阵
        }
        a[k][col] = 1;
        for (i = 0; i < equ; i++)
        {
            if (i != k)
            {
                x[i] -= x[k] * a[i][k];///x[i] 减去 (第k行的x[k]与a[i][k]的乘积),与后面的a[i][j] -= a[k][j] * a[i][col]合在一起就是每一行减去第K行
                for (j = col + 1; j < var; j++)
                {
                    a[i][j] -= a[k][j] * a[i][col];///使(其他所有行)减去(第k行)
                }
                a[i][col] = 0;
            }
        }
    }
    for (i = equ - 1; i >= 0; i--)///
    {
        bool bul = 1;
        for (j = var - 1; j >= 0; j--)
        {
            if (abs(a[i][j]) > eps)///如果有解(R(a) = R(a, x))
            {
                bul = 0;
            }
        }
        if (bul && abs(x[i]) > eps)///如果无解(R(a)<R(a, x))
        {
            return 0;
        }
    }
    int free_num = var;
    for (i = equ - 1; i >= 0; i--)///
    {
        for (j = var - 1; j >= 0; j--)
        {
            if (abs(a[i][j]) > eps)
            {
                free_num--;///计算自由元个数
                break;
            }
        }
    }
    if (free_num == 0)
    {
        return -1;
    }
    return var - free_num;
}
int main()
{
    int n, m;
    while (scanf("%d%d", &equ, &var) != EOF)
    {
        for (int i = 0; i < equ; i++)
        {
            for (int j = 0; j < var; j++)
            {
                cin >> a[i][j];
            }
            cin >> x[i];///存的是方程的结果,也就是增广矩阵的b[]
            a[i][var] = i + 1;///存这个行的序号
        }
        cout << Gauss() << endl;
        for (int i = 0; i < equ; i++)
        {
            for (int j = 0; j < var; j++)
            {
                printf("%5.2f ", a[i][j]);///输出矩阵变换后的每个数
            }
            cout << endl;
        }
        for (int i = 0; i < var; i++)
        {
            printf("%d : %.2f\n", i + 1, x[i]);///x[i]此时存的是未知数的解
        }
    }
    return 0;
}

 

posted @ 2019-07-31 09:20  明霞  阅读(931)  评论(0编辑  收藏  举报