P3389 【模板】高斯消元法

更 好 的 观 赏 体 验 \large 更好的观赏体验


原题链接

P3389
AC记录:Accepted

题目大意

给定一个线性方程组,对其求解。

Example   Explain \texttt{Example Explain} Example Explain
样例所示的方程组为:
{ x + 3 y + 4 z = 5 ( 1 ) x + 4 y + 7 z = 3 ( 2 ) 9 x + 3 y + 2 z = 2 ( 3 ) \begin{cases} x+3y+4z=5&(1)\\ x+4y+7z=3&(2)\\ 9x+3y+2z=2&(3)\\ \end{cases} x+3y+4z=5x+4y+7z=39x+3y+2z=2(1)(2)(3)

解题思路

高斯消元法的基本解题思路就是把其中的一个未知数先 系数化为一,然后再用这个未知数 消掉其他方程内的这个未知数,最后得出结果。

没看懂?用样例来解释一下。


首先把 x x x 系数化为一, ( 1 ) (1) (1) 方程已经做到了。

然后用 ( 2 ) − ( 1 ) (2)-(1) (2)(1),把 ( 2 ) (2) (2) 中的 x x x 消掉,再用 ( 3 ) − 9 × ( 1 ) (3)-9\times (1) (3)9×(1),把 ( 3 ) (3) (3) 中的 x x x 消掉,最后方程式变成:
{ x + 3 y + 4 z = 5 ( 1 ) y + 3 z = − 2 ( 2 ) − 24 y − 34 z = − 43 ( 3 ) \begin{cases} x+3y+4z=5&(1)\\ y+3z=-2&(2)\\ -24y-34z=-43&(3)\\ \end{cases} x+3y+4z=5y+3z=224y34z=43(1)(2)(3)


然后再把 y y y 系数化为一,此时就不能用到上面的 ( 1 ) (1) (1) 了,因为会导致 x x x 的出现。而这个工作也已经完成了。

然后用 ( 1 ) − 3 × ( 2 )   ,   ( 3 ) − ( − 24 ) × ( 2 ) (1)-3\times (2)\ ,\ (3)-(-24)\times(2) (1)3×(2) , (3)(24)×(2) 得到:
{ x − 5 z = 11 ( 1 ) y + 3 z = − 2 ( 2 ) 38 z = − 91 ( 3 ) \begin{cases} x-5z=11&(1)\\ y+3z=-2&(2)\\ 38z=-91&(3)\\ \end{cases} x5z=11y+3z=238z=91(1)(2)(3)


最后,就是解最后一个 z z z 了。首先,系数化为一, ( 3 ) (3) (3) 变为 z = − 91 38 z=-\frac{91}{38} z=3891,然后再把其他两个方程中的 z z z 去掉,变为:
{ x = − 37 38 ( 1 ) y = 197 38 ( 2 ) z = − 91 38 ( 3 ) \begin{cases} x=-\frac{37}{38}&(1)\\[3pt] y=\frac{197}{38}&(2)\\[3pt] z=-\frac{91}{38}&(3)\\ \end{cases} x=3837y=38197z=3891(1)(2)(3)

保留两位小数后就是:
{ x = − 0.97 ( 1 ) y = 5.18 ( 2 ) z = − 2.39 ( 3 ) \begin{cases} x=-0.97&(1)\\ y=5.18&(2)\\ z=-2.39&(3)\\ \end{cases} x=0.97y=5.18z=2.39(1)(2)(3)

和样例一样。


随后,就可以把这个推出有 n n n 个方程的结果。

而有多数解只有一种可能,就是该方程中没有此未知数,即未知数为 0 0 0

上代码

#include<bits/stdc++.h>

#define endl '\n'

using namespace std;

double  a[110][110];
int     n;

void print2DMatrix()
{
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n+1; j++)
            printf("%0.2lf ",a[i][j]);
        printf("\n");
    }
    printf("\n");
    return;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    /* Code */
    cin>>n;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n+1; j++)
            cin>>a[i][j];
    for(int i=1; i<=n; i++)
    {
        int maxpos=i;
        for(int j=i+1; j<=n; j++)
            if(a[j][i]>a[maxpos][i])
                maxpos=j;
        for(int j=1; j<=n+1; j++)
            swap(a[i][j],a[maxpos][j]);
        // print2DMatrix();
        double temp=a[i][i];
        if(temp==0)
        {
            cout<<"No Solution"<<endl;
            return 0;
        }
        for(int j=1; j<=n+1; j++)
            a[i][j]/=temp;
        for(int j=1; j<=n; j++)
        {
            if(j==i)
                continue;
            temp=a[j][i];
            for(int k=1; k<=n+1; k++)
                a[j][k]-=temp*a[i][k];
        }
        // print2DMatrix();
    }
    for(int i=1; i<=n; i++)
        printf("%0.2lf\n",a[i][n+1]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值