高斯/约旦消元法

前置数学知识

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}aijbib_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)排成mmmnnn列的数表
[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}a11a21am1a12a22am2a1na2namn
称为mmmnnn列矩阵(或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. x12x2+x3=02x2+x3=72x1+x2x3=1
我们采用增广矩阵来记录对应的每次消元
原增广矩阵:
[1−210021721−11]\begin{bmatrix} {1}&{-2}&{1}&{0}\\ {0}&{2}&{1}&{7}\\ {2}&{1}&{-1}&{1}\\ \end{bmatrix}102221111071
保留第一个方程中的x1x_1x1,并且消去其余方程中的x1x_1x1
[1−210021705−31]\begin{bmatrix} {1}&{-2}&{1}&{0}\\ {0}&{2}&{1}&{7}\\ {0}&{5}&{-3}&{1}\\ \end{bmatrix}100225113071
保留第二个方程中的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}1000202121177233
保留第三个方程中的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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值