acwing 883 高斯消元解线性方程组

题目地址

模拟初等行变换就可以了。

有很多种模拟,对于此题方便,有了这个模拟。

从第一列开始,枚举未处理的行找到最大的主元素。
交换最大主元素的行和当前行。

如果最大主元素也为0,则不处理。

把主元素的系数化为1.

把其他未处理行的主元素列的系数都消去。

继续处理,知道最后一列。

之后特判r是否把所有列处理完,没有在判断是否无解还是多解。
有则把每个x算出来。

代码上有许多步骤解释

#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include
#include
#include
#include
#include
#include
#include
#define int long long
#define sc scanf
#define pf printf
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned long long LL;
 
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
const int mod = 10000;
const int N = 210;

double a[N][N];

int gauss(int n){
	int c,r;
	for(c=1,r=1;c<=n;c++){//从第一列开始 ,r记录当前处理的行。 
		int t = r;//默认当前最大的元素为当前行 
		for(int i=r;i<=n;i++)//从当前行开始,寻找出最大的主元素(即当前列最大的元素) 
			if(fabs(a[i][c]) > fabs(a[t][c])) t = i;
		if(fabs(a[t][c]) < eps) continue;//表示这一列全部都为0,当前行没有处理完,下次继续处理这行。 
		for(int i=c;i<=n+1;i++) swap(a[r][i],a[t][i]);//把最大主元素的交换上去。 
		for(int i=n+1;i>=c;i--) a[r][i] /= a[r][c];//使当前行的主元素的系数为1,、
		//其他的系数也跟着变化,只需进行到当前列因为 前面的都为0了 
		for(int i=r+1;i<=n;i++)//从当前行的下一行开始,把所有当前列的元素变为0,其他的系数也跟着变, 
			if(fabs(a[i][c]) > eps)//为0就不用消去了 
				for(int j=n+1;j>=c;j--)
					a[i][j] -= a[r][j] * a[i][c];//表示系数的消去。 
		r ++;//处理的行数加1. 
	}
	
	if(r <= n){
		for(int i=r;i<=n;i++)
			if(fabs(a[i][n+1]) > eps)//r表示最后处理到这行时为全部的系数都为0,我们从 r行开始,判断是否有 0 == 1的情况 
				return 2;
		return 1;
	}
	//从后往前 依次消去那一行除了主元素之外的未知数。a[i][n+1]剩下的就是 1*x_ = a[i][n+1]。 
	for(int i=n-1;i>0;i--){
		for(int j=i+1;j<=n;j++)
			a[i][n+1] -= a[j][n+1] * a[i][j];
	}
	return 0;
}

signed main(){
//	IOS;
	#ifdef ddgo
		freopen("C:/Users/asus/Desktop/ddgoin.txt","r",stdin);
	#endif
	
	int n; cin>>n;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n+1;j++)
			cin>>a[i][j];
	
	int t = gauss(n);
	if(t == 0) for (int i=1;i<=n;i++) pf("%.2lf\n", a[i][n+1]);
	else if(t == 1) puts("Infinite group solutions");
	else puts("No solution");
	
	return 0;
}

你可能感兴趣的:(数论,acwing)