高斯消元解线性方程组
- 1.题目
- 2.基本思想
- 3.代码实现
1.题目
输入一个包含 n 个方程 n 个未知数的线性方程组。
方程组中的系数为实数。
求解这个方程组。
下图为一个包含 m 个方程 n 个未知数的线性方程组示例:
输入格式
第一行包含整数 n。
接下来 n n n 行,每行包含 n + 1 n+1 n+1个实数,表示一个方程的 n n n 个系数以及等号右侧的常数。
输出格式
如果给定线性方程组存在唯一解,则输出共 n n n 行,其中第 i i i 行输出第 i i i 个未知数的解,结果保留两位小数。
注意:本题有 SPJ,当输出结果为 0.00
时,输出 -0.00
也会判对。在数学中,一般没有正零或负零的概念,所以严格来说应当输出 0.00
,但是考虑到本题作为一道模板题,考察点并不在于此,在此处卡住大多同学的代码没有太大意义,故增加 SPJ
,对输出 -0.00
的代码也予以判对。
如果给定线性方程组存在无数解,则输出 Infinite group solutions
。
如果给定线性方程组无解,则输出 No solution
。
数据范围
1≤n≤100
,
所有输入系数以及常数均保留两位小数,绝对值均不超过 100
。
输入样例:
3
1.00 2.00 -1.00 -6.00
2.00 1.00 -3.00 -9.00
-1.00 -1.00 2.00 7.00
输出样例:
1.00
-2.00
3.00
2.基本思想
3.代码实现
import java.util.Scanner;//java中的Math.abs()可以用于浮点数取绝对值
//String.format("%.2f",x) %.2f"为保留两位小数,x为要输出的数字
public class Main {static int N = 110;static double a[][] = new double[N][N];static int n;static double eps = 1e-6;private static int gauss() {//高斯消元 存在答案时:a[i][n] 0<=i<nint c, r;//列 行for (c = 0, r = 0; c < n; c++) {//从列开始枚举int t = r;for (int i = r; i < n; i++) {//找到绝对值最大的行if (Math.abs(a[i][c]) > Math.abs(a[t][c])) t = i;//t行最大}if (Math.abs(a[t][c]) < eps) continue;for (int i = c; i <= n; i++) {double temp = a[t][i];a[t][i] = a[r][i];a[r][i] = temp;//将绝对值最大的行换到顶端}for (int i = n; i >= c; i--) a[r][i] /= a[r][c]; // 将当前行的首位变成1for (int i = r + 1; i < n; i++) // 用当前行将下面所有的列消成0if (Math.abs(a[i][c]) > eps)for (int j = n; j >= c; j--)a[i][j] -= a[r][j] * a[i][c];r++;}if (r < n) {for (int i = r; i < n; i++)if (Math.abs(a[i][n]) > eps) return 2;// 无解return 1;// 有无穷多组解}for (int i = n - 1; i >= 0; i--)for (int j = i + 1; j < n; j++)a[i][n] -= a[i][j] * a[j][n];return 0;}public static void main(String[] args) {Scanner sc = new Scanner(System.in);n = sc.nextInt();for (int i = 0; i < n; i++)//读入for (int j = 0; j < n + 1; j++)a[i][j] = sc.nextDouble();int t = gauss();if (t == 2) System.out.println("No solution");else if (t == 1) System.out.println("Infinite group solutions");else if (t == 0) for (int i = 0; i < n; i++) System.out.println(String.format("%.2f",a[i][n]));}
}