AcWing 883 高斯消元解线性方程组

题目描述:

输入一个包含n个方程n个未知数的线性方程组。方程组中的系数为实数。求解这个方程组。

下图为一个包含m个方程n个未知数的线性方程组示例:

9a504fc2d5628535be9dcb5f90ef76c6a7ef634a.gif

输入格式

第一行包含整数n。

接下来n行,每行包含n+1个实数,表示一个方程的n个系数以及等号右侧的常数。

输出格式

如果给定线性方程组存在唯一解,则输出共n行,其中第i行输出第i个未知数的解,结果保留两位小数。

如果给定线性方程组存在无数解,则输出“Infinite group solutions”。

如果给定线性方程组无解,则输出“No solution”。

数据范围

1≤n≤100,
所有输入系数以及常数均保留两位小数,绝对值均不超过100。

输入样例:

3
1.00 2.00 -1.00 -6.00
2.00 1.00 -3.00 -9.00
-1.00 -1.00 2.00 7.00

输出样例:

1.00
-2.00
3.00

分析:

本题是要我们实现线性代数里面的高斯消元求解线性方程组,我们往往先把增广矩阵化为行阶梯型,然后再自下而上求解各个变量。在线代里,我们往往先找第一列为1的某行,将其换到第一行,然后用该行将其它行第一列都化为0,紧接着再考虑第二列。在编程过程中,我们往往先找到某列中非零的数x所在行作为第一行(这里y总是找到该列最大的数,感觉没啥必要),也就是与当前变换的第一行交换,然后将第一行都除以x,将x化为1,再去将下面各行该列都化为0.当所有的增广矩阵都化为行阶梯型后,判断下秩的大小,本题的系数矩阵是n*n的方阵,故满秩时,有唯一解,从最后一行开始自底而上将上面各列的系数都化为0,最后留下的常数列就是方程的解;如果系数矩阵不满秩,则判断下面的行常数列是否都是0,不是说明系数矩阵的秩不等于增广矩阵的秩,方程无解,否则有无穷多解。

#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 105;
const double eps = 1e-6;
double a[maxn][maxn];
int n;
int gauss(){
    int c,r;
    for(c = 0,r = 0;c < n;c++){
        int t = r;
        for(int i = r;i < n;i++){
            //if(fabs(a[i][c]) > fabs(a[t][c]))   t = i;
            if(fabs(a[i][c]) > eps){//找到该列非0的数
                t = i;
                break;
            }
        }
        if(fabs(a[t][c]) < eps) continue;//该列都是0,直接执行下一列
        for(int i = 0;i <= n;i++)   swap(a[t][i],a[r][i]);//交换到最上面
        for(int i = n;i >= c;i--)   a[r][i] /= a[r][c];//最上面一行首个非零数化1
        for(int i = r + 1;i < n;i++){
            if(fabs(a[i][c]) > eps){//非零
                for(int j = n;j >= c;j--)   a[i][j] -= a[r][j] * a[i][c];//化0
            }
        }
        r++;
    }
    if(r < n){
        for(int i = r;i < n;i++){
            if(fabs(a[i][n]) > eps) return 2;
        }
        return 1;
    }
    for(int i = n - 1;i >= 0;i--){
        for(int j = i + 1;j < n;j++){
            a[i][n] -= a[j][n] * a[i][j];
        }
    }
    return 0;
}
int main(){
    cin>>n;
    for(int i = 0;i < n;i++){
        for(int j = 0;j <= n;j++){
            cin>>a[i][j];
        }
    }
    int res = gauss();
    if(res == 0){
        for (int i = 0; i < n; i ++ ) printf("%.2lf\n", a[i][n]);
    }
    else if(res == 1) puts("Infinite group solutions");
    else    puts("No solution");
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值