zoukankan      html  css  js  c++  java
  • [题解] [笔记]高斯消元 & 洛谷P3389

    [题解] [笔记]高斯消元 & 洛谷P3389

    算法思路

    消元

    解决多元方程组的时候我们通常的方法有两个:加减消元和代入消元。高斯消元的原理就是加减消元。那么在解方程的时候如果要加减消元那么首先就要把某一个未知数的系数化成一样的。

    放一段消元的代码

        for(int i = 1;i <= n;i++){
            if(fabs(a[i][i]) < 1e-8){//当系数很小接近于0时视为无解
                printf("No Solution");
                exit(0);
            }
            double div = a[i][i];//把方程组中第i个方程的系数化为1
            for(int j = i;j <= n + 1;j++)a[i][j] /= div;//处理第i个方程其它项的系数
            for(int j = i + 1;j <= n;j++){
                double x = a[j][i];
                for(int k = i;k <= n + 1;k++)//从第i个未知数开始,因为之前的未知数已经消过元了
                    a[j][k] -= a[i][k] * x;
            }
        }
    

    结合这段代码,我们再来理解消元的过程:

    [假设现在有方程组:egin{cases} 5x-2y=4\2x+3y=7end{cases}\ 根据代码,我们先处理第一个方程,把第一个方程的x项系数化为1\ 则第一个方程现在变成了:x-frac{2}{5}y=frac{4}{5}\ 以上的过程就是上面代码1~7行的过程。\ 再往下看,接着就是把其余的方程和第i个方程进行加减消元\ 看到上面代码的第9行,此时x=2,到第11行\ 第二个方程的第1个系数就变成了2-1*2=0\ 第二个方程的第2个系数变成3=3-frac{2}{5}*2=frac{11}{5}之后的运算同理 ]

    回代

    消完元就利用已经求解出的未知数带入原来的方程。

    回代代码

        ans[n] = a[n][n + 1];//所有的元都消完了,那么等号右边的数就是最后一个被消元的未知数的解,可以手推一下
        for(int i = n - 1;i;i--){//思考一下可以发现,倒序的原因是消元之后这个未知数就没有了,所以最后消元的未知数,含有它的方程也在越靠后面
            ans[i] = a[i][n + 1];
            for(int j = i + 1;j <= n;j++)
                ans[i] -= a[i][j] * ans[j];
        }
    

    放完整代码

    #include <bits/stdc++.h>
    using namespace std;
    int n;
    long double ans[110],a[110][110];
    void gauss(){
        for(int i = 1;i <= n;i++){
            if(fabs(a[i][i]) < 1e-8){
                printf("No Solution");
                exit(0);
            }
            double div = a[i][i];
            for(int j = i;j <= n + 1;j++)a[i][j] /= div;
            for(int j = i + 1;j <= n;j++){
                double x = a[j][i];
                for(int k = i;k <= n + 1;k++)
                    a[j][k] -= a[i][k] * x;
            }
        }
        ans[n] = a[n][n + 1];
        for(int i = n - 1;i;i--){
            ans[i] = a[i][n + 1];
            for(int j = i + 1;j <= n;j++)
                ans[i] -= a[i][j] * ans[j];
        }
    }
    int main(){
        scanf("%d",&n);
        for(int i = 1;i <= n;i++){
            for(int j = 1;j <= n + 1;j++){
                double x;
                scanf("%lf",&x);
                a[i][j] = x;
            }
        }
        gauss();
        for(int i = 1;i <= n;i++)
            printf("%.2lf
    ",(double)ans[i]);
        return 0;
    }
    
  • 相关阅读:
    openJudge计算概论-谁考了第k名
    OpenJudge计算概论-求平均年龄
    OpenJudge计算概论-能被3,5,7整除的数
    OpenJudge计算概论-计算书费
    OpenJudge计算概论-计算三角形面积【海伦公式】
    OpenWrt 中安装配置Transmission
    OpenWrt中wifidog的配置及各节点页面参数
    Linux中后台执行任务
    通过ionice和nice降低shell脚本运行的优先级
    OpenWrt中对USB文件系统的操作, 以及读写性能测试
  • 原文地址:https://www.cnblogs.com/czy--blog/p/13998623.html
Copyright © 2011-2022 走看看