题解:洛谷 P2455 [SDOI2006] 线性方程组

【题目来源】

洛谷:P2455 [SDOI2006] 线性方程组 - 洛谷 (luogu.com.cn)

【题目描述】

已知 \(n\) 元线性一次方程组。

\[\begin{cases} a_{1, 1} x_1 + a_{1, 2} x_2 + \cdots + a_{1, n} x_n = b_1 \\ a_{2, 1} x_1 + a_{2, 2} x_2 + \cdots + a_{2, n} x_n = b_2 \\ \cdots \\ a_{n,1} x_1 + a_{n, 2} x_2 + \cdots + a_{n, n} x_n = b_n \end{cases} \]

请根据输入的数据,编程输出方程组的解的情况。

【输入】

第一行输入未知数的个数 \(n\)
接下来 \(n\) 行,每行 \(n + 1\) 个整数,表示每一个方程的系数及方程右边的值。

【输出】

如果有唯一解,则输出解。你的结果被认为正确,当且仅当对于每一个 \(x_i\) 而言结果值与标准答案值的绝对误差或者相对误差不超过 \(0.01\)

如果方程组无解输出 \(-1\)
如果有无穷多实数解,输出 \(0\)

【输入样例】

3
2 -1 1 1
4 1 -1 5
1 1 1 0

【输出样例】

x1=1.00
x2=0.00
x3=-1.00

【算法标签】

《洛谷 P2455 线性方程组》 #数学# #线性代数# #高斯消元# #各省省选# #2006# #山东# #Special Judge#

【代码详解】

#include <bits/stdc++.h>
using namespace std;

const int N = 105;  // 最大矩阵大小
const double eps = 1e-6;  // 浮点数精度阈值
int n;  // 方程数量(即矩阵阶数)
double a[N][N];  // 增广矩阵

// 高斯消元法求解线性方程组
int gauss()
{
    int c, r;  // 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;
            }
        }
      
        // 如果当前列主元绝对值小于eps,说明该列全为0,跳过
        if (fabs(a[t][c]) < eps)
        {
            continue;
        }
      
        // 将主元所在行交换到第r行
        for (int i = c; i <= n; i++)
        {
            swap(a[t][i], a[r][i]);
        }
      
        // 将主元归一化为1
        for (int i = n; i >= c; i--)
        {
            a[r][i] /= a[r][c];
        }
      
        // 用第r行消去下面所有行的第c列
        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];
                }
            }
        }
        r++;  // 行指针下移
    }
  
    // 判断解的情况
    if (r < n)  // 系数矩阵秩小于n
    {
        for (int i = r; i < n; i++)
        {
            if (fabs(a[i][n]) > eps)  // 存在0=非零的情况,无解
            {
                return 2;
            }
        }
        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];
        }
    }
    return 0;  // 有唯一解
}

int main()
{
    cin >> n;  // 读入方程数量
  
    // 读入增广矩阵
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n + 1; j++)
        {
            cin >> a[i][j];
        }
    }
  
    int t = gauss();  // 执行高斯消元
  
    if (t == 0)  // 有唯一解
    {
        for (int i = 0; i < n; i++)
        {
            printf("x%d=%.2lf\n", i + 1, a[i][n]);
        }
    }
    else if (t == 1)  // 有无穷多解
    {
        cout << "0" << endl;
    }
    else  // 无解
    {
        cout << "-1" << endl;
    }
  
    return 0;
}

【运行结果】

3
2 -1 1 1
4 1 -1 5
1 1 1 0
x1=1.00
x2=0.00
x3=-1.00
posted @ 2026-02-20 20:52  团爸讲算法  阅读(10)  评论(0)    收藏  举报