高斯消元(列主元素,完全主元素,若尔当)

高斯消元法,对于ACM题目中需要用矩阵快速幂的方面很好用。可以通过打表找到的值,推出系数!!好用。

一、列主元素消元法

//列主元素消元法
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=100;
const int inf=0x7f7f7f7f;
double a[maxn][maxn];
double x[maxn];//解向量
int n;
void Xiao_gauss(int cur)//不交换列
{
    if(cur==n)
    {
        cout<<endl;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<=n;j++)
            printf("%lf  ",a[i][j]);
            cout<<endl;
        }
        return;
    }
    else{
        int id=cur;
        double max_r=0;
        for(int i=cur;i<n;i++)//找到最大值
            if(fabs(a[i][cur])>max_r) max_r=fabs(a[i][cur]),id=i;
        //cout<<id<<" "<<max_r<<endl;
        for(int i=0;i<=n;i++)//两行元素调换
        {
            double tmp=a[id][i];
            a[id][i]=a[cur][i];
            a[cur][i]=tmp;
        }

        for(int i=cur+1;i<n;i++)//除了本行下面的都要减
        {
            double t=a[i][cur]/a[cur][cur];
            for(int j=cur;j<=n;j++)//
            {
                a[i][j]=a[i][j]-a[cur][j]*t;
                //cout<<a[cur][j]<<endl;
            }
        }
        Xiao_gauss(cur+1);
        }
}
void f_x()
{
    for(int i=n-1;i>=0;i--)
    {
        double sum=0;
        for(int j=i+1;j<=n-1;j++)
            sum+=a[i][j]*x[j];
        //cout<<sum<<endl;
        x[i]=(a[i][n]-sum)/a[i][i];
    }
    for(int i=0;i<n;i++)
        cout<<"x"<<i+1<<"= "<<x[i]<<endl;
}
int main()
{

    cin>>n;
    for(int i=0;i<n;i++)
        for(int j=0;j<=n;j++)
            cin>>a[i][j];
    /*for(int j=0;j<n;j++)
        a[n+1][j]=j;
    a[n+1][n]=0.0;*/
    //列消元法。
    Xiao_gauss(0);
    f_x();

    return 0;
}
/*

3
1 2 3 14
0 1 2 8
2 4 1 13

3
0.001 2.000 3.000 1.000
-1.000 3.712 4.623 2.000
-2.000 1.072 5.643 3.000 
*/

二、完全主元素消元法

//(2)完全主元素消元法
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=100;
const int inf=0x7f7f7f7f;
double a[maxn][maxn];
double x[maxn];//解向量
int n;
void show()
{
    cout<<endl;
        for(int i=0;i<=n;i++)
        {
            for(int j=0;j<=n;j++)
            printf("%lf  ",a[i][j]);
            cout<<endl;
        }
        return;
}
void Xiao_gauss(int cur)//完全
{
    if(cur==n)
    {
        show();
        return;
    }
    else{
        int id_i=cur;
        int id_j=cur;
        double max_r=0;
        for(int i=cur;i<n;i++)//找到所有最大值
            for(int j=cur;j<n;j++)
            if(fabs(a[i][j])>max_r)
            {
                 max_r=fabs(a[i][cur]);
                 id_i=i;
                 id_j=j;
            }
        //cout<<id<<" "<<max_r<<endl;
        for(int i=0;i<=n;i++)//行元素调换
        {
            double tmp=a[id_i][i];
            a[id_i][i]=a[cur][i];
            a[cur][i]=tmp;
        }
        for(int i=0;i<=n+1;i++)//列元素交换
        {
            double tmp=a[i][id_j];
            a[i][id_j]=a[i][cur];
            a[i][cur]=tmp;
        }
        //cout<<"wanquan"<<endl;
        //show();

        for(int i=cur+1;i<n;i++)//除了本行下面的都要减
        {
            double t=a[i][cur]/a[cur][cur];
            for(int j=cur;j<=n;j++)//
            {
                a[i][j]=a[i][j]-a[cur][j]*t;
                //a[i][j]=(a[cur][cur]*a[i][j]-a[cur][j]*a[i][cur]);
                //a[i][j]/=a[cur][cur];
                //cout<<a[i][j]<<endl;
            }
        }
        //cout<<"xiaoyuan"<<endl;
        show();
        Xiao_gauss(cur+1);
        }
}
void f_x()
{
    for(int i=n-1;i>=0;i--)
    {
        double sum=0;
        for(int j=i+1;j<=n-1;j++)
            sum+=a[i][j]*x[(int)a[n][j]];
        //cout<<sum<<endl;
        //cout<<id<<endl;
        x[(int)a[n][i]]=(a[i][n]-sum)/a[i][i];
    }
    for(int i=1;i<=n;i++)
        cout<<"x"<<i<<"= "<<x[i]<<endl;
}
int main()
{

    cin>>n;
    for(int i=0;i<n;i++)
        for(int j=0;j<=n;j++)
            cin>>a[i][j];
    //赋予n+1为x代表
    for(int j=0;j<n;j++)
        a[n][j]=j+1;
    a[n][n]=0;
    //列消元法。
    Xiao_gauss(0);
    f_x();

    return 0;
}
/*

3
1 2 3 14
0 1 2 8
2 4 1 13

3
0.001 2.000 3.000 1.000
-1.000 3.712 4.623 2.000
-2.000 1.072 5.643 3.000 
*/

三、若尔当,用了列主元素


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=100;
const int inf=0x7f7f7f7f;
double a[maxn][maxn];
double x[maxn];//解向量
int n;
int gcd(int a,int b)
{
    return b?gcd(a,a%b):a;
}
void show()
{
    cout<<endl;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<=n;j++)
        printf("%lf  ",a[i][j]);
        cout<<endl;
    }
}
void Xiao_gauss(int cur)//不交换列
{
    if(cur==n)
    {
        show();
        return;
    }
    else{
        //lie主元素消元法
        /*int id=cur;
        double max_r=0;
        for(int i=cur;i<n;i++)//找到最大值
            if(fabs(a[i][cur])>max_r) max_r=fabs(a[i][cur]),id=i;
        //cout<<id<<" "<<max_r<<endl;
        for(int i=0;i<=n;i++)//两行元素调换
        {
            double tmp=a[id][i];
            a[id][i]=a[cur][i];
            a[cur][i]=tmp;
        }*/

        int tmp=a[cur][cur];
        for(int i=0;i<=n;i++)
        {
            a[cur][i]/=tmp;//变成1
        }
        //show();
        for(int i=0;i<n;i++)//每行都要操作
        {
            if(i==cur) continue;

            double t=a[i][cur]/a[cur][cur];
            for(int j=cur;j<=n;j++)//
            {
                a[i][j]=a[i][j]-a[cur][j]*t;
                //a[i][j]=(a[cur][cur]*a[i][j]-a[cur][j]*a[i][cur])/a[cur][cur];
                //cout<<a[cur][j]<<endl;
            }
        }
        //show();
        Xiao_gauss(cur+1);
        }
}
void f_x()
{
    for(int i=n-1;i>=0;i--)
    {
        //cout<<sum<<endl;
        x[i]=a[i][n];
    }
    for(int i=0;i<n;i++)
        cout<<"x"<<i+1<<"= "<<x[i]<<endl;
}
int main()
{

    cin>>n;
    for(int i=0;i<n;i++)
        for(int j=0;j<=n;j++)
            cin>>a[i][j];

    Xiao_gauss(0);
    f_x();

    return 0;
}
/*

3
1 2 3 14
0 1 2 8
2 4 1 13

3
0.001 2.000 3.000 1.000
-1.000 3.712 4.623 2.000
-2.000 1.072 5.643 3.000 

3
2 8 2 14
1 6 -1 13
2 -1 2 5
*/

猜你喜欢

转载自blog.csdn.net/miranda_ymz/article/details/81071726
今日推荐