[笔记]: 高斯消元

来源:互联网 发布:端口号对应的协议 编辑:程序博客网 时间:2024/06/01 10:17

高斯消元

是个求解线性一元多次方程的好办法

eg:

百度百科



像这个样子 把方程列成一个矩阵 矩阵的前n个元素是系数 第n+1个存的是这一个方程的答案

如 2x+3y+z=5 那么 矩阵的这一行就是 2 3 1 5

每次消掉一列使这一列的元素 为0

除了矩阵的第[i][i]个为1 最后 第 i 行的第n+1个的值 就是方程第 i 个元素的解

注意两种情况:

1.这一列都为0除了n+1这个位子上不为0 这就相当于 0x+0y+0z=n(n!=0)

那么根据小学的知识 这个方程是无解的

2.这一行每一个都为0 类似0x+0y+0z=0 

(因为x是第i行i个)那么无论x取何值 这个方程都有解 那么这个x就是自由元(又叫自由变元)

此x取何值 可能会对y和z产生影响 但方程会有解(多组)

PS:

高斯消元有两种方法:

一种是消完左下的小三角 然后从最后一个网上回带这个做法比较标准 也比较对 但是多了一步

我更喜欢的是另一种 叫

高斯-若尔当消元法(Gauss-Jordan Elimination

此做法不只是消下面的小三角 一次把一列都消掉 那么最后就不用回带 好写一点

虽然听说这个方法效率比那个低    实际上我觉得差不了多少   毕竟这个好打一点点(不用回带)

模板:洛谷的3389

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<cmath>#define eps 0.00000001using namespace std;double a[1000][1000];int main(){int n;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 k=i;for(int j=i+1;j<=n;j++)if(fabs(a[i][j])<fabs(a[k][j]))k=j;//找最大的 移到第i行(当前要求的行)去 if(fabs(a[k][i])<eps){//无解的情况 最大的是0 记得加fabs 考虑浮点误差 printf("No Solution\n");return 0;}if(k!=i){for(int j=1;j<=n+1;j++)//往第i行交换 记得是到n+1 因为答案也要算 swap(a[k][j],a[i][j]);}double tmp=a[i][i];for(int j=i;j<=n+1;j++)a[i][j]/=tmp;//a[i][i]系数化为1 for(int p=1;p<=n;p++){if(p!=i){double t=a[p][i];for(int j=i;j<=n+1;j++)a[p][j]=a[p][j]-t*a[i][j];//消元 }}}for(int i=1;i<=n;i++)printf("%.2f\n",a[i][n+1]);return 0;}


原创粉丝点击