高斯消元是用来求线性方程组的解,行列式求值,或者矩阵求逆等等。主要有两个步骤:化行阶梯形矩阵和回带。
高斯消元的时间复杂度为,以下代码中代表方程个数,代表未知数个数,数组用来判断哪些未知数是
变元,数组用来存求得的解。
代码:
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>
using namespace std;
const int N = 105;
int gcd(int a,int b)
{
return b ? gcd(b,a%b):a;
}
int lcm(int a,int b)
{
return a / gcd(a,b) * b;
}
/**n个方程,m个未知数,r代表当前处理的行,c代表当前处理的列*/
void Gauss(int a[][N],int n,int m,int &r,int &c)
{
r = c = 0;
for(; r<n && c<m; r++,c++)
{
int maxi = r;
for(int i=r+1; i<n; i++)
if(abs(a[i][c]) > abs(a[maxi][c]))
maxi = i;
if(maxi != r)
{
for(int i=r; i<m+1; i++)
swap(a[r][i],a[maxi][i]);
}
if(a[r][c] == 0)
{
r--;
continue;
}
for(int i=r+1; i<n; i++)
{
if(a[i][c] != 0)
{
int x = abs(a[i][c]);
int y = abs(a[r][c]);
int LCM = lcm(x,y);//最小公倍数
int tx = LCM / x;
int ty = LCM / y;
if(a[i][c] * a[r][c] < 0)
ty = -ty;
for(int j=c; j<m+1; j++)//主要目的是让 a[i][c]变为0
a[i][j] = a[i][j] * tx - a[r][j] * ty;
}
}
}
}
int Rewind(int a[][N],int x[],bool f[],int n,int m,int r,int c)
{
for(int i=r; i<n; i++)
if(a[i][c] != 0)
return -1;
if(r < m)//不一定能解除全部的解
{
memset(f,1,sizeof(f));
for(int i=r-1; i>=0; i--)
{
int id = 0;
int cnt = 0;
for(int j=0; j<m; j++)
{
if(a[i][j] != 0 && f[j])
{
cnt++;
id = j;//这个id是指需要解的那个x
}
}
if(cnt > 1) continue;
int t = a[i][m]; //整个方程组的值
for(int j=0; j<m; j++)
{
if(a[i][j] != 0 && j != id)
t -= a[i][j] * x[j];
}
x[id] = t / a[i][id];
f[id] = 0;//代表id这列 这个x已经被解出来了
}
return m - r;
}
for(int i=r-1; i>=0; i--)//均能解出
{
int t = a[i][c];
for(int j=i+1; j<c; j++)
{
if(a[i][j] != 0)
t -= a[i][j] * x[j];
}
if(t % a[i][i] != 0) return -2;
x[i] = t / a[i][i];
}
return 0;
}
void Print(int a[][N],int n,int m)
{
for(int i=0; i<n; i++)
{
for(int j=0; j<m+1; j++)
cout<<a[i][j]<<" ";
cout<<endl;
}
}
int a[N][N];
int x[N];
bool f[N];
int main()
{
int n,m;
while(cin>>n>>m)
{
for(int i=0; i<n; i++)
{
for(int j=0; j<m+1; j++)
cin>>a[i][j];
}
int r,c;
Gauss(a,n,m,r,c);//转化为三角形或者是阶梯形
Rewind(a,x,f,n,m,r,c);
Print(a,n,m);
puts("");
}
return 0;
}