(笔记)高斯-约旦消元法初步
高斯-约旦消元法
应用需求
高斯消元法应用于一系列求解多元一次(多元线性)方程中,运用了类似于可以手搓的二元一次方程的思想。
基本操作
将待求解的方程组视为\(n\)行\(n+1\)列的矩阵,表示有\(n\)条方程,共有\(n\)个未知数,其中第\(n+1\)列表示方程常数位。
具体地:
\[\begin{cases}
{a_{1,1}x_1+a_{1,2}x_1+...+a_{1,n}x_n=a_{1,n+1}}\\
{a_{2,1}x_1+a_{2,2}x_1+...+a_{2,n}x_n=a_{2,n+1}}\\
...\\
{a_{n,1}x_1+a_{n,2}x_1+...+a_{n,n}x_n=a_{n,n+1}}
\end{cases}
\]
表示为矩阵:
\[\begin{bmatrix}
a_{1,1} & a_{1,2} &...&a_{1,n}&|&a_{1,n+1}\\
a_{2,2} & a_{2,2} &...&a_{2,n}&|&a_{2,n+1}\\
...\\
a_{n,1} & a_{n,2} &...&a_{n,n}&|&a_{n,n+1}
\end{bmatrix}
\]
高斯消元的过程大概有以下三个步骤:
- 交换某两行的位置。
- 用一个非\(0\)的常数乘上某个方程。
- 把某一行乘\(k\)然后加到另一方程上。
过程如下:
-
先从第一列开始,选择一个非\(0\)的系数所在的行,将其与第\(1\)行交换,令选择的系数为\(a_{i,j}\)。
-
把选择的系数转换为\(1\),对于\(\forall 1\leq k\leq n+1,a_{i,k}\leftarrow \frac{a_{i,k}}{a_{i,j}}\),即将一行系数与常数同时除以\(a_{i,j}\)。
-
利用选择的行将其他行同位置消除至\(0\)。(同一位置指\(\forall a_{x,j},x\in [1,n],x\neq i\))
代码实现
//Gauss-Jordan Elimination
#include<bits/stdc++.h>
using namespace std;
const int N=105;
double eps=1e-7;
int n;
double a[N][N];
signed main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n+1;j++)
scanf("%lf",&a[i][j]);
for(int i=1;i<=n;i++){
int mx=i;
for(int j=i+1;j<=n;j++)
if(fabs(a[j][i])>fabs(a[mx][i]))//这里取可行系数取了绝对值最大值
mx=j;
if(fabs(a[mx][i])<eps){
printf("No Solution");
return 0;
}
double rec=a[mx][i];
for(int j=1;j<=n+1;j++){
swap(a[mx][j],a[i][j]);
a[i][j]/=rec;
}
for(int k=1;k<=n;k++){
if(k==i)continue;
rec=a[k][i]/a[i][i];
for(int j=1;j<=n+1;j++)
a[k][j]-=rec*a[i][j];
}
}
for(int i=1;i<=n;i++)
printf("%.2lf\n",a[i][n+1]);
return 0;
}
简单的应用
- P4035 [JSOI2008] 球形空间产生器,自己构造方程组并求解,数学题。
- SP2883 WIDGET - Widget Factory,同余方程,求出模意义下的恒等解后枚举求解即可。
- P2447 [SDOI2010] 外星千足虫,同余方程,只有\(0\)和\(1\),用bitset优化即可。
此外,高斯消元法还有概率DP求解,线性基等结合应用,读者可自行了解,本博客不进行详细介绍。

浙公网安备 33010602011771号