P3389 【模板】高斯消元法

传送门

把所有方程放到一个二维数组里

样例的数组为[ 1,3,4,5 ]

      [ 1,4,7,3 ]

      [ 9,3,2,2 ]

考虑一个一个消元

拿一个方程出来,把未知数 x 的系数化成1

用加减消元消去其他方程的 x

然后再消下一个未知数

最后一个未知数消完后再把值往上一个方程代入

最后每个未知数都求出来了

如果消 x 的时候发现所有方程的 x 的系数都是 0

那么 x 可以取任何值,就是有多个解

判一下就好了

拿方程时优先拿系数大的可以减小误差(不会证明)

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const double eps=1e-7;
double mp[107][107],ans[107];
int n;
inline void slove()
{
    for(int i=1;i<=n;i++)//消去第i位未知数
    {
        double mx=mp[i][i]; int pos=i;
        for(int j=i+1;j<=n;j++)//注意前面的方程用过了不能再用
            if(fabs(mx)<fabs(mp[j][i]))
                mx=mp[j][i],pos=j;
        swap(mp[i],mp[pos]);//找系数最大的方程

        if(fabs(mp[i][i])<eps)//判一下多解的情况
        {
            cout<<"No Solution";
            exit(0);
        }

        double div=mp[i][i];
        for(int j=i;j<=n+1;j++)
            mp[i][j]/=div;//把此方程未知数的系数化为1
        for(int j=i+1;j<=n;j++)
        {
            div=mp[j][i];
            for(int k=i;k<=n+1;k++)
                mp[j][k]-=mp[i][k]*div;//用加减消元消去其他方程的此未知数
        }
    }

    for(int i=n;i;i--)
    {
        ans[i]=mp[i][n+1];
        for(int j=i+1;j<=n;j++)
            ans[i]-=mp[i][j]*ans[j];//把后面的答案往前带
    }
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
            scanf("%lf",&mp[i][j]);
        scanf("%lf",&mp[i][n+1]);
    }

    slove();

    for(int i=1;i<=n;i++)
        printf("%.2lf\n",ans[i]);
    return 0;
}

 

posted @ 2018-09-21 13:09  LLTYYC  阅读(220)  评论(0编辑  收藏  举报