[笔记]: 高斯消元

9 篇文章 0 订阅
3 篇文章 0 订阅

高斯消元

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

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.00000001
using 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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值