AcWing883 高斯消元解线性方程组

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
#pragma warning(disable:4996)
const int N = 110;
const double eps = 1e-8;
double a[N][N];

int n;

int gauss() {
	int r , c ;
	for (r = 0, c = 0; c < n; c++) {
		//遍历每一列
		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; i++)swap(a[t][i], a[r][i]);

		//第二步
		for (int i = n; i >= c; i--)a[r][i] /= a[r][c];//将当前行的第一个数变成1
		//要从最后一列开始 否则前面全是1
		
		//第三步
		for (int i = r + 1; i < n; i++) {
			//消去这一行下的每一列
			if (fabs(a[i][c]) > eps) {//当开头数不是0时才进行处理
				for (int j = n; j >= c; j--) {
					a[i][j] -= a[i][c] * a[r][j];
					//终于想通 a[r][c]已经变成1 那么倍数一定是这一行的开头*a[r][c]=a[i][c]
					//然后每一列都减去上一列的倍数即可
				}
			}
		}
		r++;//处理下一行
		//这里为什么不直接在最外层for写呢 是因为上面有个如果开头=0那就continue下一列 不能直接跳到下一行
	}
	//第四步
	if (r < n) {
		//如果不是满秩矩阵 
		for (int i = r; i < n; i++) {
			if (fabs(a[i][n]) > eps)return 2;//如果有一行的b不等于0那就说明存在0!=0的情况 无解
		}
		return 1;
	}
	//有解
	for (int i = n-1; i >= 0; i--) {
		for (int j = i+1; j < n; j++) {
			a[i][n] -= a[j][n] * a[i][j];//倒着向上推出结果
			//只要最后一行b的结果就行
			//n-1行的b=没有-之前的a[i][n]-n行的b * n-1行中对应位置的数(倍数
		}
	}
	return 0;
}

int main() {
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n + 1; j++) {
			scanf("%lf", &a[i][j]);
		}
	}
	int t = gauss();
	if (t == 2) puts("No solution");
	else if (t == 1)puts("Infinite group solutions");
	else {
		for (int i = 0; i < n; i++) {
			if (fabs(a[i][n]) < eps) a[i][n] = 0;  // 去掉输出 -0.00 的情况
			printf("%.2lf\n", a[i][n]);
		}
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值