You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

49 lines
2.8 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
const double eps = 1e-8; // 小数的精度值
int n; // n个方程
double a[N][N]; // 系数+结果矩阵
int gauss() { // 高斯消元答案存于a[i][n]中0 <= i < n
int r = 0; // 先按行后按列进行计算当前行是第1行
for (int c = 0; c < n; c++) { // 枚举每一列
int t = r; // 防破坏r,复制出t
for (int i = r; i < n; i++) // 当前行需要找它的后续行
if (abs(a[i][c]) > abs(a[t][c])) t = i; // t的任务是找出c列中系数最大值是哪一行
if (abs(a[t][c]) < eps) continue; // 如果c列绝对值最大的系数是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]; // a[r][c]:行首系数将当前行的行首通过除法变为1,倒序
for (int i = r + 1; i < n; i++) // 用当前行r的c列通过减法将后续行c列消成0
for (int j = n; j >= c; j--) // 倒序,需要保留行首逻辑和上面是一样的行首值是变更系数如果正序就把系数变成1了后面就不对了
a[i][j] -= a[r][j] * a[i][c]; // a[i][c]:需要变化的乘法系数,减法:对位相消
r++; // 下一行
}
if (r < n) { // 如果没有成功执行完所有行意味着中间存在continue,也就是某一列的系数都是0
for (int i = r; i < n; i++)
if (abs(a[i][n]) > eps) return 0; // 系数是0但结果不是0无解
return 2; // 系数是0结果也是0x取啥都对有无穷多组解
}
// 代回求每个变量值
for (int i = n - 2; i >= 0; i--) // 行,倒序
for (int j = i + 1; j < n; j++) // 列,倒三角,右上角应该都是0,对角线全是1
a[i][n] -= a[i][j] * a[j][n]; // 系数消为0
return 1; // 有唯一解
}
int main() {
cin >> n;
for (int i = 0; i < n; i++) // n个方程
for (int j = 0; j <= n; j++) // 每行n+1个数据因为最后一列是等号右侧值
cin >> a[i][j];
int t = gauss();
if (t == 0)
puts("No solution");
else if (t == 2)
puts("Infinite group solutions");
else
for (int i = 0; i < n; i++) printf("%.2lf\n", a[i][n]); // 保留两位小数
return 0;
}