高斯消元解一类 Ai1*x1 + Ai2*x2 + ... + Ain*xn = Bi的方程

Problem 1. equation
Input file: equation.in
Output file: equation.out
Time limit: 1 second
给你n个变量组成的m方程组,第i个形如:
Ai1 * x1 + Ai2 * x2 + … + Ain * xn = Bi
现在请你帮忙解一下方程。
Input
第1行一个整数T,表示数据组数。
接下来T个方程组。
每个方程组第1行,包含两个整数n m,表示变量数和方程数。
接下来m行,每行n + 1个浮点数,表示:Ai1 Ai2 … Ain Bi。
Output
对每个方程组:
如果无解或有多组解,输出一行:”No solution or more than one solution.”
如果有唯一解,输出一行,包含n个浮点数:x1 x2 … xn,每个保留两位小数。
Sample
equation.in
2
2 3
3 4 5
5 6 7
2 1 0
2 3
3 4 5
5 6 7
2 4 7
equation.out
-1.00 2.00
No solution or more than one solution.
Note
. 对于30% 的数据,1 <= n = m <= 2;
. 对于100% 的数据,1 <= n <= m <= 100,1 <= T <= 10,-1000 <= aij ; bi <= 1000,且最多拥有两位小数。

思路:
裸的高斯消元。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;

const int N = 100 + 10;
const double eps = 1e-8;//精度是个玄学问题 

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

void gauss() {
    int cnt = 0;//统计主元数量 
    for(int i=1; i<=n; i++) {
        int j = -1;
        for(int k=cnt+1; k<=m; k++) {
            if(fabs(a[k][i]) > eps) {
                j = k; break;
            }
        }
        if(j == -1) continue;//xi是一个自由元 
        for(int k=i; k<=n+1; k++) {//不是自由元就可以把它提到当前行 
            swap(a[j][k], a[cnt+1][k]);
        }
        for(j=1; j<=m; j++) {
            if(j == cnt + 1) continue;
            if(fabs(a[j][i]) < eps) continue;//避免被零除 
            double r = a[j][i] / a[cnt+1][i];
            for(int k=i; k<=n+1; k++) {//把其他行上的这一位都消掉 
                a[j][k] -= a[cnt+1][k] * r;
            }
        }
        cnt++;
    }
    for(int i=cnt+1; i<=m; i++)
        if(fabs(a[i][n+1]) > eps) {//系数为0,却等于一个常数(无解) 
            printf("No solution or more than one solution.\n"); return;
        }
    if(cnt < n) {//主元数与变量数不同,有自由元,多解 
        printf("No solution or more than one solution.\n"); return;
    }
    for(int i=1; i<=n; i++)
        printf("%.2f ", a[i][n+1] / a[i][i]);//除了主元,其他的都被消掉了,所以直接用答案除以系数就好 
    printf("\n");
    return ;
}

int main(){
    freopen ("equation.in", "r", stdin);
    freopen ("equation.out", "w", stdout);
    int T; scanf("%d", &T);
    while( T-- ){
        scanf("%d%d", &n, &m);
        for(int i=1; i<=m; i++){
            for(int j=1; j<=n+1; j++){
                scanf("%lf", &a[i][j]);
            }
        }
        gauss();    
    }
    return 0; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值