是线性代数中的一个算法。 可用来求解线性方程组,可以求出矩阵的秩和可逆方阵的逆矩阵。
通过逐步消除未知数来将原始线性系统转化为另一个更简单的等价系统。
原理:用初等行变换将增广矩阵转换为行阶梯矩阵,然后回代求出方程解。
顺序消去法:
将 Ax = b 按照从上至下、从左至右的顺序化为上三角方程组,中间过程不对矩阵进行交换。
过程: 局限:
- 每次运算时,必须保证对角线上的元素不为0(即运算中的分母不为0),否则算法无法继续进行。
- 即使不为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 )
swap(b[r][i], b[t][i]);
for ( int i = n + 1; i >= c; --i )
b[r][i] /= b[r][c];
for ( int i = r + 1; i <= n; ++i )
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/
|