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

15 篇文章 0 订阅
13 篇文章 0 订阅

题目链接

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

#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 2
1 2 5
2 1 4
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值