社区讨论

样例不过求调

P3389【模板】高斯消元法参与者 2已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@mhj3kdfk
此快照首次捕获于
2025/11/03 20:09
4 个月前
此快照最后确认于
2025/11/03 20:09
4 个月前
查看原帖
CPP
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-6; // 避免精度问题

double a[105][105];

void solve()
{
	int n; cin >> n;
	for(int i = 1; i <= n; i ++){
		for(int j = 1; j <= n + 1; j ++){ // 第n+1列存的是等号右边的常数(消完元之后就是方程的解)
			cin >> a[i][j];
		}
	}
	
	for(int i = 1; i <= n; i ++){
		// 找到所有行中系数最大的x[i](主元),并把它交换到第i行。因为消元时每个式子都要乘上 a[j][i]/a[i][i],分母越大误差就会越小
		int maxp = i;
		for(int j = i + 1; j <= n; j ++){
			if(fabs(a[j][i]) - fabs(a[maxp][i]) > eps){ // a[j][i]>a[maxp][i]
				maxp = j;
			}
		}
		for(int j = 1; j <= n + 1; j ++){
			swap(a[i][j], a[maxp][j]);
		}
		
		if(fabs(a[i][i]) < eps){ // a[i][i]==0
			// 1.无解 矩阵最后一行出现系数都为0但等式右边不为0(n*n方程组必须对角线所有都不为0)   2.无穷多解 有一行全部为0,此时n个未知数只有n-1个方程,故有无穷多解
			cout << "No Solution\n"; return ;
		}
		
		for(int j = n + 1; j >= i; j --){ // 把当前行x[i]的系数化一(第i列之前的系数已经都是0,就不用管了)
			a[i][j] = a[i][j] / a[i][i];
		}
		
		for(int j = 1; j <= n; j ++){ // 消去其他行中的x[i]
			if(i != j){
				for(int k = 1; k <= n + 1; k ++) a[j][k] -= a[i][k] * (a[j][i] / a[i][i]);
			}
		}
		
//		for(int i = 1; i <= n; i ++){
//			for(int j = 1; j <= n + 1; j ++){
//				cerr << a[i][j] << ' ';
//			}
//			cerr <<  '\n';
//		}cerr << '\n';
	}
	
	for(int i = 1; i <= n; i ++){
		cout << fixed << setprecision(2) << a[i][n + 1] << '\n'; // 输出等号右边的常数就是解(因为消元后最后一个x[n]化为0,a[n][n+1]就是x[n]的值,向上回代同理)
	}
}

signed main()
{
	ios :: sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	solve();
	return 0;
}

回复

3 条回复,欢迎继续交流。

正在加载回复...