kuangbin大佬的高斯消元模板

dalao解释的博客

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 const int MAXN=50;
  5 int a[MAXN][MAXN];//增广矩阵
  6 int x[MAXN];//解集
  7 bool free_x[MAXN];//标记是否是不确定的变元
  8 
  9 int gcd(int a,int b){
 10     if(b == 0) return a; else return gcd(b,a%b);
 11 }
 12 inline int lcm(int a,int b){
 13     return a/gcd(a,b)*b;//先除后乘防溢出
 14 }
 15 // 高斯消元法解方程组(Gauss-Jordan elimination).(-2表示有浮点数解,但无整数解,
 16 //-1表示无解,0表示唯一解,大于0表示无穷解,并返回自由变元的个数)
 17 //有equ个方程,var个变元。增广矩阵行数为equ,分别为0到equ-1,列数为var+1,分别为0到var.
 18 int Gauss(int equ,int var){
 19     int max_r;      // 当前这列绝对值最大的行.
 20     int col;        //当前处理的列
 21     int ta,tb;
 22     int LCM;
 23     int temp;
 24     int free_x_num;
 25     int free_index;
 26     for(int i=0;i<=var;i++){
 27         x[i]=0;
 28         free_x[i]=true;
 29     }
 30     //转换为阶梯阵.
 31     col=0;      // 当前处理的列
 32     for(int k = 0;k < equ && col < var;k++,col++){// 枚举当前处理的行.
 33     // 找到该col列元素绝对值最大的那行与第k行交换.(为了在除法时减小误差)
 34         max_r=k;
 35         for(int i=k+1;i<equ;i++){
 36             if(abs(a[i][col])>abs(a[max_r][col])) max_r=i;
 37         }
 38         if(max_r!=k){// 与第k行交换.
 39             for(int j=k;j<var+1;j++) swap(a[k][j],a[max_r][j]);
 40         }
 41         if(a[k][col]==0){// 说明该col列第k行以下全是0了,则处理当前行的下一列.
 42             k--;
 43             continue;
 44         }
 45         for(int i=k+1;i<equ;i++){// 枚举要删去的行.
 46             if(a[i][col]!=0){
 47                 LCM = lcm(abs(a[i][col]),abs(a[k][col]));
 48                 ta = LCM/abs(a[i][col]);
 49                 tb = LCM/abs(a[k][col]);
 50                 if(a[i][col]*a[k][col]<0) tb=-tb;//异号的情况是相加
 51                 for(int j=col;j<var+1;j++){
 52                     a[i][j] = a[i][j]*ta-a[k][j]*tb;
 53                 }
 54             }
 55         }
 56     }
 57     // 1. 无解的情况: 化简的增广阵中存在(0, 0, ..., a)这样的行(a != 0).
 58     for (int i = k; i < equ; i++){ // 对于无穷解来说,如果要判断哪些是自由变元,那么初等行变换中的交换就会影响,则要记录交换.
 59         if (a[i][col] != 0) return -1;
 60     }
 61     // 2. 无穷解的情况: 在var * (var + 1)的增广阵中出现(0, 0, ..., 0)这样的行,即说明没有形成严格的上三角阵.
 62     // 且出现的行数即为自由变元的个数.
 63     if (k < var)
 64         return var - k; // 自由变元有var - k个.
 65     // 3. 唯一解的情况: 在var * (var + 1)的增广阵中形成严格的上三角阵.
 66     // 计算出Xn-1, Xn-2 ... X0.
 67     for (int i = var - 1; i >= 0; i--){
 68         temp = a[i][var];
 69         for (int j = i + 1; j < var; j++){
 70             if (a[i][j] != 0) temp -= a[i][j] * x[j];
 71         }
 72         if (temp % a[i][i] != 0) return -2; // 说明有浮点数解,但无整数解.
 73         x[i] = temp / a[i][i];
 74     }
 75     return 0;
 76 }
 77 
 78 int main(){
 79     int equ,var;
 80     while (scanf("%d %d", &equ, &var) != EOF){
 81         memset(a, 0, sizeof(a));
 82         for (int i = 0; i < equ; i++){
 83             for (int j = 0; j < var + 1; j++){
 84                 scanf("%d", &a[i][j]);
 85             }
 86         }
 87         int free_num = Gauss(equ,var);
 88         if (free_num == -1) printf("无解!\n");
 89         else if (free_num == -2) printf("有浮点数解,无整数解!\n");
 90         else if (free_num > 0){
 91             printf("无穷多解! 自由变元个数为%d\n", free_num);
 92             for (int i = 0; i < var; i++){
 93                 if (free_x[i]) printf("x%d 是不确定的\n", i + 1);
 94                 else printf("x%d: %d\n", i + 1, x[i]);
 95             }
 96         }else{
 97             for (int i = 0; i < var; i++){
 98                 printf("x%d: %d\n", i + 1, x[i]);
 99             }
100         }
101         printf("\n");
102     }
103     return 0;
104 }

 

posted @ 2018-09-11 20:47  ouyang_wsgwz  阅读(233)  评论(0编辑  收藏  举报