zoukankan      html  css  js  c++  java
  • AcWing 883

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

    在这里插入图片描述

    输入格式

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

    输出格式

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

    数据范围

    1≤ n ≤100
    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

    题目大意:

    先输入一个 n ,表示有 n 个未知数,接下来有 n 行,表示有 n 个线性方程,每次输入为浮点数,格式为a1x1 + a2x2 + … akxk = ni ,你要输入的是a1…ak 和 ni ,如果方程只有一组解,则第 i 行输出一个 Xi 保留两位小数,如果无解或有无穷组解则输出相应的提示。

    解题思路:

    高斯消元模板题,用一个二维数组存储增广矩阵,复杂度是O(n3) 的,高斯消元的基本思想:

    1. 从头开始枚举每一列
    2. 找所有行中这一列绝对值最大的数
    3. 将绝对值最大的数所在的行换到最上面去(这里的最上面指的是没处理过的最上面)
    4. 将这一行第一个a 消成1(这行所有的数全部除第一个数),这里要注意倒着消
    5. 将下面所有行的这一列消成 0(减去a[r][j] * a[i][c] 意为第r行(最上面的一行)第j列 × 这一行第c列(当前枚举的一列),最后就会变成 a[i][c] -= a[r][c] * a[i][c])而 a[r][c] == 1
    6. 根据 r 的值判断是否存在无穷解或无解
    7. 递推出每一个 x 的值

    Code:

    #include <iostream>
    #include <cmath>
    
    using namespace std;
    
    const int N = 110;
    const double eps = 1e-6;
    
    double a[N][N];//用于存放增广矩阵
    int n;
    
    int gauss()
    {
        int r, c;//r 行 c 列,从第1列枚举到 n - 1 列
        for (r = 0, c = 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[t][c]) < eps) continue;//满足这个条件说明该列所有数都是0,因为最大绝对值是0
            
            for (int i = c; 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;//这种情况是 n(系数) = 0的情况,一定无解
                
            return 1;//反之则是无穷组解
        }
        //如果走到这里说明有一组唯一解
        for (int i = n - 1; i >= 0; i --)
            for (int j = i + 1;  j < n; j ++)
                a[i][n] -= a[i][j] * a[j][n];//递推出来每一个x 的值,这里自己动手模拟一下就懂了
        
        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 t = gauss();
        
        if (t == 2) puts("No solution");
        else if (t == 1) puts("Infinite group solutions");
        else
        {
            for (int i = 0 ; i < n; i ++)//输出每一个未知数的值
                printf("%.2lf
    ", a[i][n]);
        }
        
        return 0;
    }
    

    PS : 高斯消元比较好理解 过程也很简单 不过代码写了两个晚上才过,太绕了 T.T 暴风哭泣

  • 相关阅读:
    Nagios显示器mysql定从库: libmysqlclient.so.18: cannot open shared object file: No such
    UVA 11402
    Oracle 11g 的PL/SQL函数结果缓存
    最大公约数(Greatest Common Divisor)
    计时器 Timer
    ArcGIS Engine 捕捉
    AE+C# 图层中增加相应属性标注
    C# ComboBox自动完成功能的示例
    Visual Assist的破解与安装
    GitHub的代码托管和使用方法
  • 原文地址:https://www.cnblogs.com/Hayasaka/p/14294136.html
Copyright © 2011-2022 走看看