天天看點

高斯消元解線性方程組

原題連結:https://www.acwing.com/activity/content/11

高斯消元解線性方程組

敲代碼的注意事項:

1.for循環中的”++”和”- -“符号要應情況而選擇,否則及容易打錯,進而出現一些非常難找到的bug

2.doule和int的類型需要注意,例如輸入輸出過程,和定義過程

3.return的類型

代碼:

#include<iostream>
#include<algorithm>
#include<cmath>

using namespace std;

const int N=110;
const double egs=1e-6;

double a[N][N];
int n;

int gause()
{
    int r,c;//r表示目前所在的行數,c表示目前所指向的列數
    for(r=0,c=0;c<n;c++)//進行n次循環,将矩陣化為三角的形式
    {
        int t=r;
        for(int i=r;i<n;i++)
         if(fabs(a[t][c])<fabs(a[i][c]))
          t=i;
        //尋找最大的數值是因為可以避免系數變得太大,精度較高.

        if(fabs(a[t][c])<egs) continue;//如果最大值是零,便可以直接跳過了
        //之是以要小于1e-6,是因為c++浮點數的一種弊端,是以小于egs時,可以近似的看作是0

        for(int i=c;i<=n;i++) swap(a[t][i],a[r][i]);
        //尋找到之後進行交換操作

        for(int i=n;i>=c;i--) a[r][i]/=a[r][c];
        //将目前第c位的值初始化為1,當然其他數也同樣需要除以第c位,之是以從第n位開始,是為了不覆寫掉第c位的值

        for(int i=r+1;i<n;i++)
          if(fabs(a[i][c])>egs)//如果目前行數為零,說明不用進行削為零的操作
           for(int j=n;j>=c;j--)
            a[i][j]-=a[i][c]*a[r][j];

        r++;
    }

    if(r<n)
    {
        for(int i=r;i<n;i++)
         if(a[i][n]>egs)
          return 2;//無解
        /*
       如果目前列的絕對值最大的值是0,那麼r還繼續停留,不轉到下一行,但c卻轉至下一行,
       由于循環過程中會進行消元操作,是以循環到該列時,下面所有行的c列就會被消成零.
       假設該列隻有零的情況出現一次的話,那麼r最終會循環到n-2行,而c卻循環到了第n-1列,
       因為循環過程中的消元,是以第n-1行的所有數都會被消成零.如果此時d不為零的話,沖突,無解;
       如果為零的話,那麼就會有無數組解.一列都是零的情況出現兩次,三次,甚至更多次都是同理.
        */
        return 1;//無數解
    }

    //将未知數求解出來
    for(int i=n-1;i>=0;i--)//i,j表示'行'的同時也表示'列'
     for(int j=i+1;j<n;j++)
      a[i][n]-=a[j][n]*a[i][j];

    return 0;//有唯一解
}

int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
     for(int j=0;j<=n;j++)
      scanf("%lf",&a[i][j]);

    int t=gause();

    if(t==0)
    {
        for(int i=0;i<n;i++) printf("%.2lf\n",a[i][n]);
    }
    else if(t==1) printf("Infinite group solutions");
    else printf("No solution");

    return 0;
}
           

繼續閱讀