首页 > 其他分享 >高斯消元

高斯消元

时间:2023-12-21 19:13:06浏览次数:24  
标签:int max ++ var include col 高斯消

高斯消元

设有n个未知数m个方程的线性方程组

\[\begin{cases} a_{11}x_{1}+a_{12}x_{2}+\dots+a_{1n}x{n}=b_{1} \\ a_{21}x_{1}+a_{22}x_{2}+\dots+a_{2n}x{n}=b_2 \\ \dots \dots \\ a_{m1}x_1+a_{m2}x_{2}+\dots+a_{mn}x_{n}=b_m \end{cases} \]

其中\(a_{ij}\)是第i个方程的第j个未知数的系数,\(b_i\)是第i个方程的常数项,\(i=1,2,\dots,m;j=1,2,\dots,n\)

image.png

代码实现

在化简为上三角矩阵的过程之中,通常要保证选择的主元的绝对值尽可能的大,以减小数值计算的精度误差

#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <array>
using namespace std;
#define x first
#define y second
#define eps 1e-6
typedef pair<int, int> PII;
typedef long long LL;
const int N = 220;
double a[N][N],x[N]; //方程左边的矩阵和等式右边的值,求解后x存的就是结果
int equ,var; // 方程数和未知数个数
int n;
//返回0表示无解1表示有解
int Gauss()
{
	// k表示当前判断是否要交换的行号,max_r是包括k当前要寻找的未知数的最大系数的行号
	int i,j,k,col,max_r;
	for(k = 0, col = 0; k < equ && col < var; k++, col++)
	{
		max_r = k;
		for(i = k + 1; i < equ; i++)
			if(fabs(a[i][col]) > fabs(a[max_r][col]))
				max_r = i; // 找到当前未知数的绝对值最大的系数的行号
		if(fabs(a[max_r][col]) < eps) return 0; // 如果系数当前要找的未知数系数等于0,则不管无穷解还是无解均返回0
		if(k != max_r)
		{
			// 将当前行换为绝对值系数最大的那一行
			for(j = col; j < var; j++) 
				swap(a[k][j],a[max_r][j]);
			swap(x[k],x[max_r]);
		}
		// 系数化为1
		x[k] /= a[k][col];
		for(j = col + 1; j < var; j++) a[k][j] /= a[k][col];
		a[k][col] = 1;
		// 将其他行的该位置未知数系数变为0
		for(i = 0; i < equ; i++)
			if(i != k)
			{
				x[i] -= x[k] * a[i][col];
				for(j = col + 1; j < var; j++) a[i][j] -=a[k][j]*a[i][col];
				a[i][col] = 0;
			}
	}
	for(int i = 0; i < n; i++) printf("%.10f\n", x[i] / a[i][i]);
	
	return 1;
}
int main()
{	
	scanf("%d",&n);
	equ = var = n;
	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < n; j++) scanf("%lf",&a[i][j]);
		scanf("%lf",&x[i]);
	}
	if(!Gauss()) printf("-1\n");

	return 0;
}

简单应用

求行列式的值

  • 将矩阵A进行高斯消元,交换两行时sgn*=-1(符号)
  • 最后将对角线上的值全部相乘,再乘以sgn即可

矩阵求逆

  • 将矩阵A和单位矩阵E横向链接,然后进行高斯消元
  • 将A编程单位矩阵时,E就变成了A的逆矩阵\(A_1\)

例题

image.png

#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <array>
using namespace std;
#define x first
#define y second
#define eps 1e-6
typedef pair<int, int> PII;
typedef long long LL;
const int N = 220;
double a[N][N],x[N]; //方程左边的矩阵和等式右边的值,求解后x存的就是结果
int equ,var; // 方程数和未知数个数
int n;
//返回0表示无解1表示有解
int Gauss()
{
	// k表示当前判断是否要交换的行号,max_r是包括k当前要寻找的未知数的最大系数的行号
	int i,j,k,col,max_r;
	for(k = 0, col = 0; k < equ && col < var; k++, col++)
	{
		max_r = k;
		for(i = k + 1; i < equ; i++)
			if(fabs(a[i][col]) > fabs(a[max_r][col]))
				max_r = i; // 找到当前未知数的绝对值最大的系数的行号
		if(fabs(a[max_r][col]) < eps) return 0; // 如果系数当前要找的未知数系数等于0,则不管无穷解还是无解均返回0
		if(k != max_r)
		{
			// 将当前行换为绝对值系数最大的那一行
			for(j = col; j < var; j++) 
				swap(a[k][j],a[max_r][j]);
			swap(x[k],x[max_r]);
		}
		// 系数化为1
		x[k] /= a[k][col];
		for(j = col + 1; j < var; j++) a[k][j] /= a[k][col];
		a[k][col] = 1;
		// 将其他行的该位置未知数系数变为0
		for(i = 0; i < equ; i++)
			if(i != k)
			{
				x[i] -= x[k] * a[i][col];
				for(j = col + 1; j < var; j++) a[i][j] -=a[k][j]*a[i][col];
				a[i][col] = 0;
			}
	}
	for(int i = 0; i < n; i++) printf("%.10f\n", x[i] / a[i][i]);
	
	return 1;
}
int main()
{	
	scanf("%d",&n);
	equ = var = n;
	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < n; j++) scanf("%lf",&a[i][j]);
		scanf("%lf",&x[i]);
	}
	if(!Gauss()) printf("-1\n");

	return 0;
}

image.png

image.png

// Problem: 开关问题
// Contest: Virtual Judge - POJ
// URL: https://vjudge.net/problem/POJ-1830
// Memory Limit: 29 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <array>
using namespace std;
#define x first
#define y second
typedef pair<int, int> PII;
typedef long long LL;
int n,test,c[101],d[101];
int a[101][101],b[101];

void gauss()
{
	int l = 1;
	for(int i = 1; i <= n; i++)
	{
		for(int  j = l; j <= n; j++)
			if(a[j][i])
			{
				for(int k = i; k <= n; k++)
					swap(a[j][k], a[l][k]);
				swap(b[j],b[l]);
				break;
			}
		if(!a[l][i]) continue;
		for(int j = 1; j <= n; j++)
		{
			if(j != l && a[j][i])
			{
				for(int k = i; k <= n; k++)
					a[j][k] ^= a[l][k];
				b[j] ^= b[l];
			}
		}
		l++;
	}
	for(int i = l; i <= n;i++)
	{
		if(b[i])
		{
			printf("-1\n");
			return ;
		}
	}
	printf("%d\n", 1 << (n-l+1));
}

int main()
{	
	scanf("%d",&test);
	while(test--)
	{
		scanf("%d",&n);
		for(int i = 1; i <= n; i++) scanf("%d",&c[i]);
		for(int i = 1; i <= n; i++) scanf("%d",&d[i]);
		for(int i = 1; i <= n; i++) b[i] = c[i]^d[i];
		memset(a,0,sizeof(a));
		for(int i = 1; i <= n; i++) a[i][i] = 1;
		int x,y;
		while(scanf("%d%d",&x,&y),x && y)
			a[y][x] = 1;
		gauss();
	}

	return 0;
}

标签:int,max,++,var,include,col,高斯消
From: https://www.cnblogs.com/viewoverlooking/p/17919912.html

相关文章

  • 高斯消元
    作用解线性方程组,将其系数和常数放在矩阵中,利用加减消元,得到一个倒三角,反着代入计算即可。double型可以选最大的一行交换,减少误差。异或型可以bitset优化,加减变^,乘除变&。稀疏矩阵可以手动代入消元,减少计算量。Link......
  • 2023.11.8 高斯消元记录
    2021ICPC沈阳I题https://link.zhihu.com/?target=https%3A//ac.nowcoder.com/acm/contest/24346/I2020ICPC济南A题https://ac.nowcoder.com/acm/contest/10662/A高斯消元只要构造出增广矩阵,求解就很简单了.对本题来说,矩阵乘开后,新矩阵的列向量,就是B*C的列向量.......
  • 高斯消元
    问题求解线性方程组算法思想高斯消元法的实现主要分为两种,一种是普通的高斯消元,将系数矩阵消为上三角矩阵,再一步步回代求出所有未知数;第二种是高斯-约旦消元法,将系数矩阵消为对角矩阵,不需要回代即可直接解出未知数,这里展示第二种做法。代码实现例题:P3389【模板】高斯消元法......
  • 浅谈高斯消元法
    2023.6.16:发布2023.8.29:修缮,加上自己觉得通俗易懂的理解,更新矩阵求逆。高斯消元高斯消元可以用于线性方程组求解或者行列式计算,求矩阵的逆等等,也算是比较基础的一个思想。消元法定义消元法是将方程组中的一方程的未知数用含有另一未知数的代数式表示,并将其带入到另一方程中,......
  • 【学习笔记】简单数论-高斯消元与线性空间
    友情提示本博客内部分内容因缺乏样例,可能晦涩难懂,建议参考蓝书或者数论小白都能看懂的线性方程组及其解法。线性方程组线性方程组是由\(M\)个\(N\)元一次方程共同构成的。线性方程组的所有系数可以写成一个\(M\)行\(N\)列的系数矩阵,再加上每个方程等号右侧的常数,可......
  • 高斯消去法python代码
    高斯消去法实现多元线性方程组求解1.流程概述高斯消去法(GaussianElimination)是一种用于求解多元线性方程组的常用方法。它通过将方程组表示为增广矩阵的形式,然后进行一系列的行变换,将增广矩阵转化为上三角矩阵,最后利用回代法求解方程组。以下是高斯消去法的流程:步骤操作......
  • 高斯消元法
    高斯消元法-约当消元法\(m\)个一次方程,\(n\)个变量,可以得到\(m\)行\(n+1\)列的增广矩阵将增广矩阵通过行初等变换为行最简形我们观察增广矩阵,线性方程组的解有\(3\)种情况唯一解有无穷多组解无解高斯-约旦消元法,是高斯消元法的一种,消元的结果是一个简化阶梯矩阵、消......
  • 高斯消元法求线性方程组
    高斯消元法作用可以快速求解n元线性方程组:\[\begin{cases}a_{11}x_1+a_{12}x_2+a_{13}x_3+\dots+a_{1n}x_n=b_1\\a_{21}x_1+a_{22}x_2+a_{23}x_3+\dots+a_{2n}x_n=b_2\\\dots\\a_{n1}x_1+a_{n2}x_2+a_{n3}x_3+\dots+a_{nn}x_{n}=b_n\\\end{cases}\]思路利用线性代数......
  • 【高斯消元】 HDOJ 5257 翻转游戏
    如果第一行的状态确定了,那么矩阵的所有状态也会随之确定。。。那么我们就将第一行写成变量,这样能够推出矩阵的m个方程。。。然后对于k,可以写出k个限制方程。。因此我们总共列出m+k个方程,高斯消元,bitset优化即可。。。#include<iostream>#include<queue>#include<stack>#inclu......
  • 「学习笔记」高斯消元
    简单说:高斯消元就是我们初中学的解方程组时用的加减消元法和代入消元法,只是高斯这个人最后总结了一下过程给定方程组\[\left\{\begin{aligned}3x+2y+z=10\quad&(1)\\5x+y+6z=25\quad&(2)\\2x+3y+4z=20\quad&(3)\\\end{aligned}\right.\]我们用......