洛谷题单指南-基础线性代数-P2455 [SDOI2006] 线性方程组
原题链接:https://www.luogu.com.cn/problem/P2455
题意解读:求解n元线性一次方程组。
解题思路:
高斯消元是求解n元线性一次方程组的经典算法,主要过程如下:
1、增广矩阵
首先,将方程组的所有系数和值提取出来,构成一个n * (n + 1)的增广矩阵。

2、行列变换
对矩阵进行如下行列变换,可以保证对应的方程组的解不变。
- 交换两行:比如把第 1 行和第 3 行交换,只是调整方程顺序;相当于交换1/3两行方程。
- 某一行乘以非零常数:比如第 1 行全乘 1/2,方程等价;相当于第一行方程乘以1/2。
- 某一行的 k 倍加到另一行:比如第 1 行 ×3 加到第 2 行,消去第 2 行的 x 项;相当于将第1行方程×3 加到第 2 行方程。
3、消元过程
高斯消元的目标是要通过行列变换,将矩阵变成对角线矩阵,也就是除了对角线和第n+1列,其余都是0。

实现过程如下:
从第1行开始,设开始行row
遍历每列,设当前列col
找到该列值最大的行,与开始行交换(如果最大列植是0,则直接跳过,处理下一个列)
将row行col列变成1,也就是该行都除以a[row][col]
将除row行以外的行col列变成0,也就是都减去row行乘以a[其余行][col]
row行处理完毕,row++
4、解的判断
如果在三角系数中
所有系数都不为0,则有唯一解。
如果系数都是0,值也是0,即0=0的情况,有无穷多解。
如果系数都是0,值不为0,即0=非0的情况,无解。
100分代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 55;
const double EPS = 1e-6;
double a[N][N];
int n;
int gauss()
{
int row = 1; //当前行
for(int col = 1; col <= n; col++) //枚举当前列
{
int t = row;
for(int i = row + 1; i <= n; i++) //找到当前列绝对值最大的行,目的是为了避免溢出,因为将最大的数变为1后,再做乘法溢出的风险会大大降低
if(fabs(a[i][col]) > fabs(a[t][col]))
t = i;
if(fabs(a[t][col]) < EPS) continue; //如果当前列绝对值最大的行是0,则继续枚举下一列
for(int i = col; i <= n + 1; i++) swap(a[t][i], a[row][i]); //将当前列绝对值最大的行与当前行交换
for(int i = n + 1; i >= col; i--) a[row][i] /= a[row][col]; //将当前行当前列的元素变为1
for(int i = 1; i <= n; i++) //将当前列的其它行消成0
{
if(i == row) continue;
for(int j = n + 1; j >= col; j--)
a[i][j] -= a[row][j] * a[i][col];
}
row++; //继续下一行
}
if(row <= n)
{
for(int i = row; i <= n; i++)
if(fabs(a[i][n + 1]) > EPS) //无解
return -1;
return 0; //无穷多解
}
return 1; //唯一解
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n + 1; j++)
cin >> a[i][j];
int res = gauss();
if(res == 1)
{
for(int i = 1; i <= n; i++)
{
printf("x%d=%.2lf\n", i, a[i][n + 1]);
}
}
else cout << res;
return 0;
}
浙公网安备 33010602011771号