题目描述
高斯消元!
样例
输入样例:
3
1.00 2.00 -1.00 -6.00
2.00 1.00 -3.00 -9.00
-1.00 -1.00 2.00 7.00
输出样例:
1.00
-2.00
3.00
具体解析如下:
C++ 代码
#include<bits/stdc++.h>
using namespace std;
const int N=107;
double a[N][N];
const double epis=1e-6;
int n;
int gause()
{
int r,c;
for(r=0,c=0;c<n;c++)//进行n次循环,将“系数矩阵”化为上三角的形式
{
int t=r;//t表示了当前第c列的元素的绝对值最大数的行数标号;
//寻找最大的绝对值是因为可以避免系数变得太大,精度较高.
for(int i=r;i<n;i++)
if(fabs(a[i][c])>fabs(a[t][c]))
t=i;
//若该列最大绝对值都是等于0,则该列所有数都会等于0;
//用epis而不直接用0:是因为C++的浮点数的精度问题,不能做到浮点数直接与0比较,而用epis这个比较小的数可以做这个判断;
if(fabs(a[t][c])<epis) continue;//continue是因为该列不会对上三角的形成做贡献,即目标上三角对角线上在该行的"1"未能形成(故r++是放在后面而没有在for循环里);
for(int i=c;i<=n;i++) swap(a[t][i],a[r][i]);// 交换行的操作(注意此时是对“整个增广矩阵”操作),第t行与第r行进行交换:之所以是和r行换是为了形成上三角;
//当前列c的目标上三角的对角线上的数即a[r][c]变为1,则所做操作是当前行r提出一个数a[r][c];
for(int i=n;i>=c;i--) a[r][i]/=a[r][c];//为了不在运算过程中改变a[r][c]的值,从第n位开始操作;
//当前列的上三角对角线上元素以下的数都变为0;
for(int i=r+1;i<n;i++)
{
if(fabs(a[i][c])>epis)//若a[i][c]为0,自然可以省去对i行的操作;
for(int j=n;j>=c;j--)
a[i][j]-=a[i][c]*a[r][j];//要使a[i][c]值为0,即i行进行减去第r行的倍数的操作;
}
r++;//若该行已经成功贡献了目标上三角对角线上的"1",则移步到下一行进行构成上三角的操作;
}
//上三角的形式形成了,下一步就是判断此时的增广矩阵解的情况了;
if(r<n)//说明剩下方程的个数是小于 n 的,判断是无解还是无穷多解;
{
for(int i=r;i<n;i++)
{
// 因为已经是完美阶梯型,所以r~n-1行的值应该都为0,也就是对应方程的左侧==0;
if(fabs(a[i][n])>epis) return 0;//即对应方程的右侧!= 0,形成了矛盾,故无解;
}
return 1;//则对于每一行,对应方程右侧==0,即形成0 = 0,故无数解;
}
//r==n,即唯一解的情况
//求解未知数
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];
return 3;
}
int main()
{
scanf("%d",&n);
//输入n行n+1列数据
for(int i=0;i<n;i++)
for(int j=0;j<=n;j++)
cin >> a[i][j];
int k=gause();
if(k==0) puts("No solution");
else if(k==1) puts("Infinite group solutions");
else
{
for(int i=0;i<n;i++) printf("%.2lf\n",a[i][n]);
}
return 0;
}