一.高斯消元解线性方程组
题目:输入一个增广矩阵,输出所有的解
分析:如果出现 0 = x(>0) 无解, 0 = 0 无穷多解, 完美梯形就是唯一解
代码:
1 #include <iostream> 2 #include <algorithm> 3 #include <cmath> 4 5 using namespace std; 6 7 const int N = 110; 8 const double eps = 1e-6; 9 10 int n; 11 double a[N][N]; 12 13 14 int gauss() 15 { 16 int c, r;// c 代表 列 col , r 代表 行 row 17 for (c = 0, r = 0; c < n; c ++ ) 18 { 19 int t = r;// 先找到当前这一列,绝对值最大的一个数字所在的行号 20 for (int i = r; i < n; i ++ ) 21 if (fabs(a[i][c]) > fabs(a[t][c])) 22 t = i; 23 24 if (fabs(a[t][c]) < eps) continue;// 如果当前这一列的最大数都是 0 ,那么所有数都是 0,就没必要去算了,因为它的约束方程,可能在上面几行 25 26 for (int i = c; i < n + 1; i ++ ) swap(a[t][i], a[r][i]);//// 把当前这一行,换到最上面(不是第一行,是第 r 行)去 27 for (int i = n; i >= c; i -- ) a[r][i] /= a[r][c];// 把当前这一行的第一个数,变成 1, 方程两边同时除以 第一个数,必须要到着算,不然第一个数直接变1,系数就被篡改,后面的数字没法算 28 for (int i = r + 1; i < n; i ++ )// 把当前列下面的所有数,全部消成 0 29 if (fabs(a[i][c]) > eps)// 如果非0 再操作,已经是 0就没必要操作了 30 for (int j = n; j >= c; j -- )// 从后往前,当前行的每个数字,都减去对应列 * 行首非0的数字,这样就能保证第一个数字是 a[i][0] -= 1*a[i][0]; 31 a[i][j] -= a[r][j] * a[i][c]; 32 33 r ++ ;// 这一行的工作做完,换下一行 34 } 35 36 if (r < n)// 说明剩下方程的个数是小于 n 的,说明不是唯一解,判断是无解还是无穷多解 37 {// 因为已经是阶梯型,所以 r ~ n-1 的值应该都为 0 38 for (int i = r; i < n; i ++ )// 39 if (fabs(a[i][n]) > eps)// a[i][n] 代表 b_i ,即 左边=0,右边=b_i,0 != b_i, 所以无解。 40 return 2; 41 return 1;// 否则, 0 = 0,就是r ~ n-1的方程都是多余方程 42 } 43 // 唯一解 ↓,从下往上回代,得到方程的解 44 for (int i = n - 1; i >= 0; i -- ) 45 for (int j = i + 1; j < n; j ++ ) 46 a[i][n] -= a[j][n] * a[i][j];//因为只要得到解,所以只用对 b_i 进行操作,中间的值,可以不用操作,因为不用输出 47 48 return 0; 49 } 50 51 int main() 52 { 53 cin >> n; 54 for (int i = 0; i < n; i ++ ) 55 for (int j = 0; j < n + 1; j ++ ) 56 cin >> a[i][j]; 57 58 int t = gauss(); 59 60 if (t == 0) 61 { 62 for (int i = 0; i < n; i ++ ) printf("%.2lf ", a[i][n]); 63 } 64 else if (t == 1) puts("Infinite group solutions"); 65 else puts("No solution"); 66 67 return 0; 68 }
二.高斯消元解异或线性方程组
题目:
输入一个包含n个方程n个未知数的异或线性方程组。
方程组中的系数和常数为0或1,每个未知数的取值也为0或1。
求解这个方程组。
异或线性方程组示例如下:
M[1][1]x[1] ^ M[1][2]x[2] ^ … ^ M[1][n]x[n] = B[1]
M[2][1]x[1] ^ M[2][2]x[2] ^ … ^ M[2][n]x[n] = B[2]
…
M[n][1]x[1] ^ M[n][2]x[2] ^ … ^ M[n][n]x[n] = B[n]
其中“^”表示异或(XOR),M[i][j]表示第i个式子中x[j]的系数,B[i]是第i个方程右端的常数,取值均为0或1。
输入格式
第一行包含整数n。
接下来n行,每行包含n+1个整数0或1,表示一个方程的n个系数以及等号右侧的常数。
输出格式
如果给定线性方程组存在唯一解,则输出共n行,其中第i行输出第i个未知数的解。
如果给定线性方程组存在多组解,则输出“Multiple sets of solutions”。
如果给定线性方程组无解,则输出“No solution”。
数据范围
1≤n≤1001≤n≤100
输入样例:
3
1 1 0 1
0 1 1 0
1 0 0 1
输出样例:
1
0
0
1 #include <iostream> 2 using namespace std; 3 4 const int N = 110; 5 int a[N][N]; 6 int n; 7 8 int gauss(){ 9 int c, r; 10 for(c = r = 0;c < n;++c){ 11 int t = r; 12 13 //在当前列找到值为1的 14 for(int i = r;i < n;++i) 15 if(a[i][c]) 16 t = i; 17 if(!a[t][c]) continue; 18 19 //和r行交换 20 for(int i = c;i <= n;++i) swap(a[r][i], a[t][i]); 21 22 //当前列消0 23 for(int i = r + 1;i < n;++i) 24 if(a[i][c]) 25 for(int j = n;j >= c;--j) 26 a[i][j] ^= a[r][j]; 27 28 ++r; 29 } 30 31 if(r < n){ 32 for(int i = r;i < n;++i) 33 if(a[i][n]) return 2; 34 return 1; 35 } 36 //这块就背了 37 for (int i = n - 1; i >= 0; i -- ) 38 for (int j = i + 1; j < n; j ++ ) 39 a[i][n] ^= a[i][j] * a[j][n]; 40 41 return 0; 42 } 43 44 int main(){ 45 cin >> n; 46 47 for (int i = 0; i < n; i ++ ) 48 for (int j = 0; j < n + 1; j ++ ) 49 cin >> a[i][j]; 50 51 int t = gauss(); 52 53 if (t == 0) 54 { 55 for (int i = 0; i < n; i ++ ) cout << a[i][n] << endl; 56 } 57 else if (t == 1) puts("Multiple sets of solutions"); 58 else puts("No solution"); 59 60 return 0; 61 }