0
点赞
收藏
分享

微信扫一扫

【Luogu 3389】【模板】高斯消元法(用高斯消元求解线性方程组)

小编 2023-02-08 阅读 58


1、线性方程组

【Luogu 3389】【模板】高斯消元法(用高斯消元求解线性方程组)_i++

2、高斯消元法

步骤1:通过一系列的加减消元,得到类似 kx=b 的式子,求得最后一个未知量的结果
步骤2:然后逐一回代求解整个 x 向量

以下列方程为例:

【Luogu 3389】【模板】高斯消元法(用高斯消元求解线性方程组)_高斯消元_02


第一次加减消元,用第1式子消去后面所有的x得到:

【Luogu 3389】【模板】高斯消元法(用高斯消元求解线性方程组)_ci_03


第一次加减消元,用第2个式子消去后面所有的y得到:

【Luogu 3389】【模板】高斯消元法(用高斯消元求解线性方程组)_高斯消元_04


这样就完成了高斯消元的步骤1,形成了一个倒三角形的形状,接下来主意回代即可。

3、用矩阵表示高斯消元

(1)消元过程:

【Luogu 3389】【模板】高斯消元法(用高斯消元求解线性方程组)_i++_05


(2)无解: 当消元完毕后,发现有一行系数都为 0,但是常数项不为 0,此时无解

例如:

【Luogu 3389】【模板】高斯消元法(用高斯消元求解线性方程组)_ci_06


(3)多解: 当消元完毕后,发现有多行系数、常数项均为 0,此时多解,有几行为全为 0,就有几个自由元,即变量的值可以任取,有无数种情况可以满足给出的方程组

例如:

【Luogu 3389】【模板】高斯消元法(用高斯消元求解线性方程组)_ci_07

,此时自由元为2个

4、例题:Luogu3389,高斯消元模板

【Luogu 3389】【模板】高斯消元法(用高斯消元求解线性方程组)_i++_08


思路:

  • 首先我们用第一列中(所有的x中)系数最大的来消其他两个式子。我们将这个选中的系数置为1。(由于最多也只能用double型存储,所以必然会有精度误差。但如果我们每次都选用最大系数的来消掉其他系数,就可以最大程度地来减小误差。)
  • 在置为1之后,我们用这个式子去消其他的式子。那么在最后,我们只需要将这个矩阵的最右下角(也就是最后一个元的实际值)不断回带即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 110;
const double eps=1e-7;

int n; double a[maxn][maxn], ans[maxn];
int Gauss(){
//1. 用第i个式子消去第i个系数,求得倒三角
for(int i = 1; i <= n; i++){
//找第i列中系数最大的式子并交换
int r = i;
for(int j=i+1; j<=n; j++){
if(abs(a[r][i])<abs(a[j][i]))r=j;
}
if(i!=r)swap(a[i],a[r]);

//如果下面的都是0,则存在多解.(n-i+1)为自由元个数
if(abs(a[i][i])<eps)return 0;

//用这个式子去消自己和其他的式子
double div = a[i][i];
for(int j = i; j <= n+1; j++)a[i][j] /= div;
for(int j = i+1; j <= n; j++){
div = a[j][i];
for(int k = i; k <= n+1; k++)
a[j][k] -= a[i][k]*div;
}
}
//2. 回代求答案值
ans[n] = a[n][n+1];
for(int i = n-1; i >= 1; i--){
ans[i] = a[i][n+1];
for(int j = i+1; j <= n; j++)
ans[i] -= a[i][j]*ans[j];
}
return 1;
}

int main(){
cin>>n;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n+1; j++)
cin>>a[i][j];
int ok = Gauss();
if(ok==1){
for(int i = 1; i <= n; i++)
printf("%.2lf\n",ans[i]);
}else{
printf("No Solution\n");
}
return 0;
}


举报

相关推荐

0 条评论