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;
}