zoukankan      html  css  js  c++  java
  • 高斯消元

    一.高斯消元解线性方程组

    题目:输入一个增广矩阵,输出所有的解

    分析:如果出现 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 }
    View Code

    二.高斯消元解异或线性方程组

    题目:

    输入一个包含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”。

    数据范围

    1n1001≤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 }
    View Code
  • 相关阅读:
    面试题58 二叉树的下一个结点
    面试题57 删除链表中重复的结点
    面试题56 链表中环的入口结点
    面试题55 字符流中第一个不重复的字符
    面试题54 表示数值的字符串
    面试题50 树中两个结点的最低公共祖先
    面试题53 正则表达式匹配
    面试题52 构建乘积数组
    面试题51 数组中重复的数字
    Qt链接库出错version Qt_5 not defined
  • 原文地址:https://www.cnblogs.com/sxq-study/p/12270129.html
Copyright © 2011-2022 走看看