模拟初等行变换就可以了。
有很多种模拟,对于此题方便,有了这个模拟。
从第一列开始,枚举未处理的行找到最大的主元素。
交换最大主元素的行和当前行。
如果最大主元素也为0,则不处理。
把主元素的系数化为1.
把其他未处理行的主元素列的系数都消去。
继续处理,知道最后一列。
之后特判r是否把所有列处理完,没有在判断是否无解还是多解。
有则把每个x算出来。
代码上有许多步骤解释
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<iomanip>
#include<cstdio>
#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;
}