前置数学知识
n元线性方程是具有如下形式的方程:
a1x1+a2x2+a3x3+…+anxn=ba_1x_1+a_2x_2+a_3x_3+…+a_nx_n = ba1x1+a2x2+a3x3+…+anxn=b
其中,a1,a2,...a_1,a_2,...a1,a2,...以及常数项bbb均为已知的实数或者复数;x1,x2,...xnx_1,x_2,...x_nx1,x2,...xn是未知变量。nnn为正整数。
同理,一个nnn元线性方程组就是由多个nnn元线性方程组成的。一个含m个方程的n元线性方程组形如:
{a11x1+a12x2+...+a1nxn=b1a21x1+a22x2+...+a2nxn=b2...am1x1+am2x2+...+amnxn=bn
\left\{
\begin{matrix}
a_{11}x_1+a_{12}x_2+...+a_{1n}x_n = b_1 \\
a_{21}x_1+a_{22}x_2+...+a_{2n}x_n = b_2\\
...\\
a_{m1}x_1+a_{m2}x_2+...+a_{mn}x_n = b_n\\
\end{matrix}
\right.
⎩⎨⎧a11x1+a12x2+...+a1nxn=b1a21x1+a22x2+...+a2nxn=b2...am1x1+am2x2+...+amnxn=bn
其中,aija_{ij}aij和bib_ibi都是已知的数,我们称上诉方程组为m×nm\times nm×n线性方程组。
当bib_ibi全为000时,称上诉线性方程组为齐次线性方程组。
当bib_ibi不全为000时,称上诉线性方程组为非齐次线性方程组。
线性方程组的解有三种情况:(1)无解,(2)有唯一解,(3)有无穷多个解。如果一个线性方程组有唯一解或无穷多个解,则称它是相容的,如果无解则称它是不相容的。
高斯消元中的实现(线性代数部分)还涉及到矩阵相关的知识,这里也补充一下:
由m×nm\times nm×n个(实或复)数aij(i=1,2,...,m;j=1,2,...,n)a_{ij}(i = 1,2,...,m;j = 1,2,...,n)aij(i=1,2,...,m;j=1,2,...,n)排成mmm行nnn列的数表
[a11a12⋯a1na21a22⋯a2n⋮⋮⋱⋮am1am2⋯amn]\begin{bmatrix}
{a_{11}}&{a_{12}}&{\cdots}&{a_{1n}}\\
{a_{21}}&{a_{22}}&{\cdots}&{a_{2n}}\\
{\vdots}&{\vdots}&{\ddots}&{\vdots}\\
{a_{m1}}&{a_{m2}}&{\cdots}&{a_{mn}}\\
\end{bmatrix}a11a21⋮am1a12a22⋮am2⋯⋯⋱⋯a1na2n⋮amn
称为mmm行nnn列矩阵(或m×nm\times nm×n矩阵),简称矩阵。数aija_{ij}aij称为矩阵的第iii行第jjj列的元素。
一个线性方程组中每个变量的系数以及常数项按照它们在方程组中的位置构成的矩阵,称为方程组的增广矩阵。利用矩阵记号,我们可以简化求解线性方程组。
运用行化简法求解线性方程组
两个基本概念:
矩阵的非零行(非零列)是指至少包含一个非零元素的行(列)。
行的非零首元或首项元素是指非零行中最左边的非零元素。
满足下列条件的矩阵为行阶梯形矩阵:
(1).可划出一条阶梯线,线的下方全为零。
(2).每个台阶只有一行,台阶数即是非零行的行数,阶梯线的竖线后面的第一个元素为非零元,即非零行的第一个非零元。
Example:

在行阶梯形矩阵的基础上,满足下列三个条件的矩阵为约旦阶梯形矩阵(Jordan阶梯形矩阵):
(1).行阶梯形矩阵。
(2).各非零行的首非零元均为1。
(3).首非零元所在列其他元素均为0。
Example:

我们要解决nnn元线性方程组的问题,只需要利用初等行变换把矩阵化为约旦阶梯形矩阵。
来个例子引入一下
{x1−2x2+x3=02x2+x3=72x1+x2−x3=1
\left\{
\begin{matrix}
x_1-2x_2+x_3 = 0 \\
2x_2+x_3 = 7\\
2x_1+x_2-x_3 = 1\\
\end{matrix}
\right.
⎩⎨⎧x1−2x2+x3=02x2+x3=72x1+x2−x3=1
我们采用增广矩阵来记录对应的每次消元
原增广矩阵:
[1−210021721−11]\begin{bmatrix}
{1}&{-2}&{1}&{0}\\
{0}&{2}&{1}&{7}\\
{2}&{1}&{-1}&{1}\\
\end{bmatrix}102−22111−1071
保留第一个方程中的x1x_1x1,并且消去其余方程中的x1x_1x1
[1−210021705−31]\begin{bmatrix}
{1}&{-2}&{1}&{0}\\
{0}&{2}&{1}&{7}\\
{0}&{5}&{-3}&{1}\\
\end{bmatrix}100−22511−3071
保留第二个方程中的x2x_2x2,并且消去其余方程中的x2x_2x2
[1027021700−112−332]\begin{bmatrix}
{1}&{0}&{2}&{7}\\
{0}&{2}&{1}&{7}\\
{0}&{0}&{-\frac{11}{2}}&{-\frac{33}{2}}\\
\end{bmatrix}10002021−21177−233
保留第三个方程中的x3x_3x3,并且消去其余方程中的x3x_3x3,(同时将第三个方程的x3x_3x3的系数化为111)
[100102040013]\begin{bmatrix}
{1}&{0}&{0}&{1}\\
{0}&{2}&{0}&{4}\\
{0}&{0}&{1}&{3}\\
\end{bmatrix}100020001143
整理一下变成
[100101020013]\begin{bmatrix}
{1}&{0}&{0}&{1}\\
{0}&{1}&{0}&{2}\\
{0}&{0}&{1}&{3}\\
\end{bmatrix}100010001123
所以最后方程组的解为
{x1=1x2=2x3=3
\left\{
\begin{matrix}
x_1 = 1 \\
x_2 = 2\\
x_3 = 3\\
\end{matrix}
\right.
⎩⎨⎧x1=1x2=2x3=3
其实,上诉所用的方法就叫高斯/约旦消元法,这里运用了初等行变换。
代码实现(高斯消元法)
教材上所学的其实是高斯/约旦消元法。就是把增广矩阵化成了行最简矩阵。
有一点不一样的是,这个代码最后反代时用了类似递推的思想(从后往前计算答案)
#include<bits/stdc++.h>
#define re register
#define maxn 105
#define eps 1e-6
using namespace std;
int n;
double a[maxn][maxn],ans[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
for(re int i = 1;i <= n;i++)
for(re int j = 1;j <= n+1;j++)
cin >> a[i][j];
for(re int i = 1;i <= n;i++)
{
int r = i;
for(re int j = i+1;j <= n;j++)
if(fabs(a[r][i]) < fabs(a[j][i]))r = j;
if(fabs(a[r][i]) < eps)
{
cout << "No Solution" << '\n';
return 0;
}
if(r != i)swap(a[r],a[i]);
double div = a[i][i];
for(re int j = i;j <= n+1;j++)
a[i][j] = a[i][j]/div;
for(re int j = i+1;j <= n;j++)
{
div = a[j][i];
for(re int k = i;k <= n+1;k++)
a[j][k] = a[j][k]-a[i][k]*div;
}
}
ans[n] = a[n][n+1];
for(re int i = n-1;i >= 1;i--)
{
ans[i] = a[i][n+1];
for(re int j = i+1;j <= n;j++)
ans[i] = ans[i]-a[i][j]*ans[j];
}
for(re int i = 1;i <= n;i++)
cout << fixed << setprecision(2) << ans[i] << '\n';
return 0;
}
954

被折叠的 条评论
为什么被折叠?



