#1195 : 高斯消元·一(模板题)

来源:互联网 发布:饥荒数据修改易宁 编辑:程序博客网 时间:2024/05/21 10:02

题目链接

高斯消元,使用列主元的方法即可。
如果使用浮点数计算的话,要注意精度问题,还有一个题目的讲解有个小问题,我的提问

#include<bits/stdc++.h>using namespace std;#define cl(a,b) memset(a,b,sizeof(a))#define fastIO ios::sync_with_stdio(false);cin.tie(0);#define LL long long#define pb push_back#define gcd __gcd#define For(i,j,k) for(int i=(j);i<k;i++)#define lowbit(i) (i&(-i))#define _(x) printf("%d\n",x)const double EPS = 1e-8;const int maxn = 1e3+2000;const int inf  = 1 << 28;/*Gauss—Jordan消元算法a 是增广矩阵,n个未知数,m个方程式l 是否是自由变元,系数矩阵的秩就是非自由变元的个数,l[i]==true:表示有界变量res 解空间的维数返回值:解空间的维数。res=0:唯一解,res=-1无解*/void out(int n,double a[][maxn]){    for(int i=0;i<n;i++){        for(int j=0;j<=n;j++){            cout<<a[i][j]<<' ';        }        cout<<endl;    }    cout<<"---------------"<<endl;}bool isZero(double x){    return fabs(x)<EPS;//think is zero}inline int solve(double a[][maxn],const int&n,const int &m,bool l[],double ans[]){    int res = 0, r = 0;    for(int i=0;i<n;i++)l[i] = false;    for(int i=0;i<n;i++){        int pv = r;        for(int j=r;j<m;j++){            if(fabs(a[j][i]) > fabs(a[pv][i])) pv = j;        }        if(r != pv) swap(a[r],a[pv]);        if(isZero(a[r][i])){            ++res;            continue;        }        for(int j=0;j<m;j++)//化简出对角,该列除r行之外的行的该列为0            if(j != r && !isZero(a[j][i])){                double tmp = a[j][i] / a[r][i];                for(int k=i+1;k<=n;k++){                    a[j][k] -= tmp * a[r][k];                }                a[j][i] = 0;            }        l[i] = true; ++r;        //debug out(a,n);    }    //r行以后的是不是存在(0,0...,a)a!=0的情况    for(int i=r;i<m;i++){        if(!isZero(a[i][n]))return -1;    }    //计算每个值    for(int i=0;i<n;i++)if(l[i])        for(int j=0;j<m;j++)if(fabs(a[j][i])>0)            ans[i] = a[j][n] / a[j][i];    return res;}int n,m;double a[maxn][maxn];bool l[maxn];double ans[maxn];int main(){    cin>>n>>m;    for(int i=0;i<m;i++){        for(int j=0;j<=n;j++){            cin>>a[i][j];        }    }    int res = solve(a,n,m,l,ans);    if(res==0){        for(int i=0;i<n;i++){            printf("%d\n",(int)round(ans[i]));        }    }    else if(res==-1){        puts("No solutions");    }    else puts("Many solutions");    return 0;}/*2 21 2 52 1 4*/
0 0