高斯消元法(Gauss Elimination)

是线性代数中的一个算法。
可用来求解线性方程组,可以求出矩阵的秩可逆方阵的逆矩阵

通过逐步消除未知数来将原始线性系统转化为另一个更简单的等价系统。

原理:用初等行变换将增广矩阵转换为行阶梯矩阵,然后回代求出方程解

顺序消去法:

将 Ax = b 按照从上至下、从左至右的顺序化为上三角方程组,中间过程不对矩阵进行交换。

过程
在这里插入图片描述
局限

  1. 每次运算时,必须保证对角线上的元素不为0(即运算中的分母不为0),否则算法无法继续进行。
  2. 即使不为0,但如果绝对值很小,由于第k次运算中在分母位置,因此除数会引起很大的误差,从而影响算法的稳定性。

列(全)主元消去法

列主元消去法

在第 k 步消元前,先找出 k 行下所有第 k 列元素最大的非零元素a[r,k],将第 r 行与第 k 行进行整行交换。

这样既不影响原方程的解,也可以将绝对值最大的a[r,k]作为主元,放在除数的位置上,尽可能减小引入误差。

全主元消去法

与列主元消去法类似,不过是从第 k 行第 k 列开始的右下角矩阵中所有元素中选取一个最大元素作为主元,同时交换 r 行与 c 列,从而保证稳定性。

const int N = 15;

int n;
double a[N][N], b[N][N];

void Gauss()
{
	//化成上三角矩阵
	for ( int r = 1, c = 1; r <= n; ++r, ++c )
	{	
		int t = r;
		for ( int i = r + 1; i <= n; ++i ) //找到主元
			if (fabs(b[i][c]) > fabs(b[t][c]))
				t = i;
			
		for ( int i = c; i <= n + 1; ++i )	//交换第 r 行和第 t 行元素
			swap(b[r][i], b[t][i]);
			
		for ( int i = n + 1; i >= c; --i )	//主元归一(第 r 行除以主元系数)
			b[r][i] /= b[r][c];
			
		for ( int i = r + 1; i <= n; ++i )	//消元(用该行把下面所有行的第c列消为0)
			for ( int j = n + 1; j >= c; --j )
				b[i][j] -= b[r][j] * b[i][c];
	}
	//化成行最简阶梯型矩阵
	for ( int i = n; i > 1; --i )
		for ( int j = i - 1; j >= 1; --j )
		{
			b[j][n + 1] -= b[i][n + 1] * b[j][i];
			b[j][i] = 0;
		}
}

signed main()
{
	scanf("%d", &n);
	for ( int i = 0; i <= n; ++i )
		for ( int j = 1; j <= n; ++j )
			scanf("%lf", &a[i][j]);

	//转化为线性方程组
	for ( int i = 1; i <= n; ++i )
		for ( int j = 1; j <= n; ++j )
		{
			b[i][j] = 2 * (a[i][j] - a[0][j]);
			b[i][n + 1] += a[i][j] * a[i][j] - a[0][j] * a[0][j];
		}
		
	Gauss();
	
	for ( int i = 1; i <= n; ++i )
		printf( "%.3lf ", b[i][n + 1]);
	return 0;
}


题:https://www.acwing.com/solution/content/48342/

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
高斯消元法是一种线性代数求解线性方程组的常用方法,它通过一系列的变换将增广矩阵为上三角矩阵,从而求出方程组的解。 下面我们来详细介绍高斯消元法的步骤: 1. 将增广矩阵写成一个矩阵形式:$$\left[\begin{array}{cccc|c}a_{11} & a_{12} & \cdots & a_{1n} & b_1 \\a_{21} & a_{22} & \cdots & a_{2n} & b_2 \\\vdots & \vdots & \ddots & \vdots & \vdots \\a_{n1} & a_{n2} & \cdots & a_{nn} & b_n \\\end{array}\right]$$ 2. 选择第一列系数最大的作为第一步的主元素所在的,将该移到第一。 3. 通过消元操作将第一列的其他元素变成零。具体地,对于第 $i$ ,我们将其乘以一个系数 $m_i$ 加到第一上,使得第一的第 $i$ 个元素变成零。需要注意的是,系数 $m_i$ 的取值为:$$m_i = -\frac{a_{i1}}{a_{11}}$$ 4. 将第二列系数最大的作为第二步的主元素所在的,将该移到第二。 5. 通过消元操作将第二列的其他元素变成零。具体地,对于第 $i$ ,我们将其乘以一个系数 $m_i$ 加到第二上,使得第二的第 $i$ 个元素变成零。需要注意的是,系数 $m_i$ 的取值为:$$m_i = -\frac{a_{i2}}{a_{22}}$$ 6. 重复上述步骤,直到将增广矩阵为上三角矩阵。此时,方程组的解可以通过回代得到。 7. 回代过程:从最后一开始,依次求解每个未知量。具体地,对于第 $i$ 个未知量,我们先将第 $i$ 的解代入第 $i$ 个方程,然后依次代入已知的第 $i+1$ 到第 $n$ 个未知量的解,得到第 $i$ 个未知量的解。 下面是高斯消元法的代码实现: ```c++ const double eps = 1e-8; int gauss(vector<vector<double>>& a, vector<double>& b) { int n = a.size(); int m = a[0].size() - 1; vector<int> p(n); for (int i = 0; i < n; i++) { p[i] = i; } for (int k = 0; k < m; k++) { int pivot = k; for (int i = k; i < n; i++) { if (abs(a[i][k]) > abs(a[pivot][k])) { pivot = i; } } swap(a[pivot], a[k]); swap(b[pivot], b[k]); if (abs(a[k][k]) < eps) { return -1; } for (int i = k + 1; i < n; i++) { double f = a[i][k] / a[k][k]; b[i] -= f * b[k]; for (int j = k; j < m; j++) { a[i][j] -= f * a[k][j]; } } } vector<double> x(m); for (int k = m - 1; k >= 0; k--) { x[k] = b[k]; for (int i = k + 1; i < m; i++) { x[k] -= a[k][i] * x[i]; } x[k] /= a[k][k]; } return 0; } ``` 其,输入参数为一个 $n \times (m+1)$ 的增广矩阵 $A$ 和一个长度为 $n$ 的向量 $b$,输出为 $0$ 或者 $-1$,表示方程组有唯一解或者无解,解存储在长度为 $m$ 的向量 $x$ 。 需要注意的是,为了防止精度误差,我们在进消元操作时,如果某个数的绝对值小于一个极小值 $\epsilon$,则将其视为零。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值