【数学】高斯消元
1. 算法简介#
高斯消元法(Gauss–Jordan elimination)是求解线性方程组的经典算法。
例如求解下列方程组:
形式化的,高斯消元可用于求解类似于
的方程组。
2. 算法理论#
2.1 高斯消元#
先将线性方程组转化为矩阵:
显然为一个
我们希望将它消成上三角的形式,如下:
我们可以枚举对角线,依次将对角线下面的所有数消成
例如第一次操作利用
变成:
依次类推消掉下三角的所有数,消成上三角的形式:
然后回带,依次相减。消成对角线的形式:
则答案
判断解的情况:
- 若
使得 且 ,则方程组无解; - 若
使得 且 ,则方程组有无数解;
误差处理:
- 由于误差传递,要将
写成 ; - 为了减小误差,每次将小的数除以大的数再去消元;
2.1 高斯-约旦消元#
对于矩阵
枚举对角线
高斯消元为每一次往下消元,而高斯-约旦消元为每一次将除本行的其他行全部消元。
由于每一次都会将除对角线外的所有数消成
不需要高斯消元的回带过程。
3. 算法实现#
luoguP3389 【模板】高斯消元法#
高斯消元模板
#include<bits/stdc++.h>
#define int long long
#define For(i,l,r) for(int i=l;i<=r;++i)
#define FOR(i,r,l) for(int i=r;i>=l;--i)
#define eqs 1e-7
using namespace std;
const int N = 1e3 + 10;
int n;
double a[N][N];
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
For(i,1,n) {
For(j,1,n+1) {
cin >> a[i][j];
}
}
for (int i = 1; i <= n - 1; ++i) {
For(j,i+1,n) if(fabs(a[i][i]) < fabs(a[j][i])) swap(a[i], a[j]);
if(fabs(a[i][i]) < eqs) continue;
For(j,i+1,n) {
double w = a[j][i] / a[i][i];
For(l,i,n+1) {
a[j][l] -= w * a[i][l];
}
}
}
for (int i = n; i >= 2; --i) {
if(fabs(a[i][i]) < eqs) continue;
FOR(j,i-1,1) {
double w = a[j][i] / a[i][i];
For(l,i,n+1) {
a[j][l] -= w * a[i][l];
}
}
}
For(i,1,n) {
int cnt0 = 0;
For(j,1,n) {
cnt0 += (a[i][j] == 0);
}
if(cnt0 == n) return puts("No Solution"), 0;
}
For(k,1,n) {
printf("%.2lf\n", a[k][n+1] / a[k][k]);
}
return 0;
}
/*
9 3 2 2
0 3.66667 6.77778 2.77778
0 0 -1.15152 2.75758
9 0 2 -13.5526
0 3.66667 0 19.0088
0 0 -1.15152 2.75758
*/
luoguP2455 [SDOI2006] 线性方程组#
高斯-约旦模板。
高斯消元的华点在于这样一组样例:
4
0 0 1 1 2
0 0 1 0 1
0 0 0 1 1
0 0 0 0 0
0
直接用高斯消元模板会出现对角线全
#include<bits/stdc++.h>
#define ll long long
#define For(i,l,r) for(int i=l;i<=r;++i)
#define FOR(i,r,l) for(int i=r;i>=l;--i)
#define eps 1e-9
using namespace std;
const int N = 55;
int n;
double a[N][N];
bool st[N];
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
For(i,1,n) {
For(j,1,n+1) {
cin >> a[i][j];
}
}
For(i,1,n) {
For(j,1,n) if(fabs(a[i][i]) < fabs(a[j][i]) && !st[j]) swap(a[i], a[j]), swap(st[i], st[j]);
if(fabs(a[i][i]) < eps) continue;
st[i] = 1;
For(j,1,n) {
if(i == j) continue;
double w = a[j][i] / a[i][i];
For(l,1,n+1) {
a[j][l] -= w * a[i][l];
}
}
}
For(i,1,n) if(fabs(a[i][i]) < eps && fabs(a[i][n+1]) > eps) return puts("-1"), 0;
For(i,1,n) if(fabs(a[i][i]) < eps && fabs(a[i][n+1]) < eps) return puts("0"), 0;
For(k,1,n) {
printf("x%d=%.2lf\n", k, a[k][n+1] / a[k][k]);
}
return 0;
}
作者:Daniel-yao
出处:https://www.cnblogs.com/Daniel-yao/p/18308249
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具