高斯消元

//高斯消元 時間複雜度O(n^3) 使用浮點數計算
#include<iostream>
#include<string.h>
#include<math.h>
using namespace std;
const double eps=1e-8;
const int maxn=101;
double a[maxn][maxn];
bool l[maxn];
double ans[maxn];

int n,m;
int t;
void print();
//也可以避免實數運算 使用輾轉相減的方法 多一個log的時間複雜度
//特別適合於行列式求值 取模操作 (除法要求逆元)
int solve()
{
    //a爲方程組對應的矩陣
    //l,ans存儲解  l[]表示是否爲自由變元 1表示不是 0表示是
    //n爲未知數的個數 m爲方程的個數
    //如果無解返回-1 否則返回自由變元數
    int res=0,r=0;//r爲第幾行 res爲自由變元數
    for(int i=0; i<n; ++i) l[i]=false; //開始都是自由變元

    for(int i=0; i<n; ++i) //枚舉列
    {

        for(int j=r; j<m; ++j) //枚舉行
            if(fabs(a[j][i])>eps)
            {
                //找到當前列下從第r行開始第一個不爲零的元素並交換到第r行
                //如果一直爲0 則下面會continue res++ 即自由變元+1
                //如果有不爲0的 把它調上來(交換行)
                for(int k=i; k<=n; ++k) //第j行和第r行交換 因爲a[j][i]!=0
                    swap(a[j][k],a[r][k]);
                break;
            }
//        print();
        //從a[r][i]這一個元素開始 往下的每個元素都是0了 所以這個元素xi是自由變元 i+1跳過即可
        if(fabs(a[r][i])<eps)
        {
            ++res;
            continue;
        }

        for(int j=0; j<m; ++j) //j是行數 從第一行(j=0)開始  讓上三角更簡潔 這樣後面求ans就沒有必要從下往上了
            if(j!=r && fabs(a[j][i])>eps)
            {
                double tmp=a[j][i]/a[r][i];
                for(int k=i; k<=n; ++k)
                    a[j][k]-=tmp*a[r][k];
            }
        l[i]=true,++r;
    }

    //檢查是否無解
    for(int i=n-res; i<m; ++i)
    {
        if(fabs(a[i][n])>eps) return -1;
    }


    //下面求結果
    for(int i=0; i<n; ++i)
        if(l[i])//不是自由變元
            for(int j=0; j<n; ++j)
                if(fabs(a[j][i])>eps)
                    ans[i]=a[j][n]/a[j][i];
    return res;//返回自由變元數
}
void print()
{
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<=n; j++)
        {
            cout<<a[i][j]<<' ';
        }
        cout<<endl;

    }

}

int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    m=n;
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<=m; j++)
        {
            cin>>a[i][j];
        }

    }
    cout<<solve()<<endl;
    print();

//    cin>>t;
//    while(t--)
//    {
//        cin>>n;
//        m=n;
//        int ta,tb;
//        memset(a,0,sizeof(a));
//        for(int i=0; i<n; ++i) cin>>a[i][n],a[i][i]=1;
//        for(int i=0; i<n; ++i) cin>>ta,a[i][n]=int(a[i][n])^ta;
//        while(cin>>ta>>tb&&(ta+tb))
//        {
//            a[tb-1][ta-1]=1;
//        }
//        res=solve(a,l,ans,n,m);
//        if(res==-1) cout<<"Oh,it's impossible~!!"<<endl;
//        else cout<<(1<<res)<<endl;
//    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章