高斯消元
#include <cstdio>
const int N=104;
double a[N][N];
int n;
double fabs(double x) {return x>0?x:-x;}
void swap(int i,int j)
{
double tmp;
for(int k=i;k<=n+1;k++)
{
tmp=a[i][k];
a[i][k]=a[j][k];
a[j][k]=tmp;
}
}
bool gauss()
{
for(int i=1;i<=n;i++)//枚举每一行
{
double m_max=0.0;
int id;
for(int j=i;j<=n;j++)//找到最大的当前系数,减小精度误差
if(m_max<fabs(a[j][i]))
{
m_max=fabs(a[j][i]);
id=j;
}
if(m_max<1e-8)//判断是否存在唯一解
return false;
swap(i,id);//交换到最大系数
//下面的代码尽可能的减小了常数并提高了精度
double now=a[i][i];
for(int j=i;j<=n+1;j++)//将首项除成1,也是唯一的除法运算
a[i][j]/=now;
for(int j=i+1;j<=n;j++)
{
now=a[j][i];//此时的now即为第i行要乘的系数(消i列)
for(int k=i;k<=n+1;k++)
a[j][k]-=a[i][k]*now;//其他项的系数处理
}
}
for(int i=n;i>=1;i--)
for(int j=i-1;j>=1;j--)
{
a[j][n+1]-=a[i][n+1]*a[j][i];
//用第i行已经出来的式子,为...0 0 0 1 0 0 0...a(右边常数)
//对上面每一行的式子都搞一遍,消去这个未知数
a[j][i]=0;
}
return true;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n+1;j++)
scanf("%lf",&a[i][j]);
if(gauss())
{
for(int i=1;i<=n;i++)
printf("%.2lf ",a[i][n+1]);
}
else
printf("No Solution");
return 0;
}
-
这是个死东西。
-
注意精度问题和常数优化