高斯消元

#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;
}

  • 这是个死东西。

  • 注意精度问题常数优化

posted @ 2018-05-06 21:31  露迭月  阅读(150)  评论(0编辑  收藏  举报